2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2016-01-15 14:57:40 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +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.
|
2008-12-02 14:17:16 +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.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2013-10-16 12:10:22 +02:00
|
|
|
#include "qmakeproject.h"
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2013-10-16 12:10:22 +02:00
|
|
|
#include "qmakeprojectmanager.h"
|
2013-08-13 10:52:57 +02:00
|
|
|
#include "qmakeprojectimporter.h"
|
|
|
|
#include "qmakebuildinfo.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "qmakestep.h"
|
2013-10-16 12:10:22 +02:00
|
|
|
#include "qmakenodes.h"
|
|
|
|
#include "qmakeprojectmanagerconstants.h"
|
|
|
|
#include "qmakebuildconfiguration.h"
|
|
|
|
#include "findqmakeprofiles.h"
|
2009-06-22 14:32:54 +02:00
|
|
|
|
2014-06-04 13:11:25 +02:00
|
|
|
#include <utils/algorithm.h>
|
2011-04-12 12:17:19 +02:00
|
|
|
#include <coreplugin/icontext.h>
|
2014-03-11 18:09:23 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2010-03-10 16:55:37 +01:00
|
|
|
#include <coreplugin/progressmanager/progressmanager.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>
|
2016-01-18 11:56:54 +01:00
|
|
|
#include <cpptools/projectpartbuilder.h>
|
2016-01-13 14:12:15 +01:00
|
|
|
#include <cpptools/projectpartheaderpath.h>
|
2014-07-24 11:48:30 +02:00
|
|
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
2013-05-29 20:18:51 +02:00
|
|
|
#include <projectexplorer/buildmanager.h>
|
2012-08-20 12:41:52 +02:00
|
|
|
#include <projectexplorer/buildtargetinfo.h>
|
|
|
|
#include <projectexplorer/deploymentdata.h>
|
2010-11-01 14:14:17 +01:00
|
|
|
#include <projectexplorer/toolchain.h>
|
2011-02-28 16:50:14 +01:00
|
|
|
#include <projectexplorer/headerpath.h>
|
2011-08-18 16:46:44 +02:00
|
|
|
#include <projectexplorer/target.h>
|
2016-09-23 15:53:31 +02:00
|
|
|
#include <projectexplorer/taskhub.h>
|
2010-09-27 17:22:57 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
2013-05-29 20:18:51 +02:00
|
|
|
#include <proparser/qmakevfs.h>
|
2011-05-20 21:40:53 +02:00
|
|
|
#include <qtsupport/profilereader.h>
|
2012-09-03 18:31:44 +02:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2014-10-20 17:23:07 +02:00
|
|
|
#include <qtsupport/qtversionmanager.h>
|
2016-01-15 16:12:54 +01:00
|
|
|
#include <cpptools/generatedcodemodelsupport.h>
|
2014-06-06 15:34:38 +02:00
|
|
|
#include <resourceeditor/resourcenode.h>
|
2016-01-15 16:12:54 +01:00
|
|
|
#include <extensionsystem/pluginmanager.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDebug>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QFileSystemWatcher>
|
2013-04-17 12:33:56 +02:00
|
|
|
#include <QMessageBox>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
using namespace QmakeProjectManager;
|
|
|
|
using namespace QmakeProjectManager::Internal;
|
2008-12-02 12:01:29 +01:00
|
|
|
using namespace ProjectExplorer;
|
2014-06-04 12:50:10 +02:00
|
|
|
using namespace Utils;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-09-19 09:15:52 +02:00
|
|
|
enum { debug = 0 };
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
namespace QmakeProjectManager {
|
2008-12-02 12:01:29 +01:00
|
|
|
namespace Internal {
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
class QmakeProjectFile : public Core::IDocument
|
2011-08-18 16:46:44 +02:00
|
|
|
{
|
|
|
|
public:
|
2016-01-08 11:09:37 +01:00
|
|
|
QmakeProjectFile(const QString &filePath);
|
2011-08-18 16:46:44 +02:00
|
|
|
|
2015-06-04 15:54:10 +02:00
|
|
|
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const override;
|
|
|
|
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) override;
|
2011-08-18 16:46:44 +02:00
|
|
|
};
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
/// Watches folders for QmakePriFile nodes
|
2011-08-18 16:46:44 +02:00
|
|
|
/// use one file system watcher to watch all folders
|
|
|
|
/// such minimizing system ressouce usage
|
|
|
|
|
|
|
|
class CentralizedFolderWatcher : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
2013-10-29 14:22:31 +01:00
|
|
|
CentralizedFolderWatcher(QmakeProject *parent);
|
2016-01-07 18:01:04 +01:00
|
|
|
|
2014-02-26 10:36:29 +02:00
|
|
|
void watchFolders(const QList<QString> &folders, QmakePriFileNode *node);
|
|
|
|
void unwatchFolders(const QList<QString> &folders, QmakePriFileNode *node);
|
2011-08-18 16:46:44 +02:00
|
|
|
|
2016-01-07 18:01:04 +01:00
|
|
|
private:
|
2011-08-18 16:46:44 +02:00
|
|
|
void folderChanged(const QString &folder);
|
|
|
|
void onTimer();
|
|
|
|
void delayedFolderChanged(const QString &folder);
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProject *m_project;
|
2011-08-18 16:46:44 +02:00
|
|
|
QSet<QString> recursiveDirs(const QString &folder);
|
|
|
|
QFileSystemWatcher m_watcher;
|
2014-02-26 10:36:29 +02:00
|
|
|
QMultiMap<QString, QmakePriFileNode *> m_map;
|
2011-08-18 16:46:44 +02:00
|
|
|
|
|
|
|
QSet<QString> m_recursiveWatchedFolders;
|
|
|
|
QTimer m_compressTimer;
|
|
|
|
QSet<QString> m_changedFolders;
|
|
|
|
};
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
// QmakeProjectFiles: Struct for (Cached) lists of files in a project
|
|
|
|
class QmakeProjectFiles {
|
2012-04-24 15:49:09 +02:00
|
|
|
public:
|
2008-12-02 12:01:29 +01:00
|
|
|
void clear();
|
2013-10-29 14:22:31 +01:00
|
|
|
bool equals(const QmakeProjectFiles &f) const;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
QStringList files[FileTypeSize];
|
|
|
|
QStringList generatedFiles[FileTypeSize];
|
2008-12-02 12:01:29 +01:00
|
|
|
QStringList proFiles;
|
|
|
|
};
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProjectFiles::clear()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
|
|
|
files[i].clear();
|
|
|
|
generatedFiles[i].clear();
|
|
|
|
}
|
|
|
|
proFiles.clear();
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProjectFiles::equals(const QmakeProjectFiles &f) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i)
|
|
|
|
if (files[i] != f.files[i] || generatedFiles[i] != f.generatedFiles[i])
|
|
|
|
return false;
|
|
|
|
if (proFiles != f.proFiles)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
inline bool operator==(const QmakeProjectFiles &f1, const QmakeProjectFiles &f2)
|
2008-12-02 12:01:29 +01:00
|
|
|
{ return f1.equals(f2); }
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
inline bool operator!=(const QmakeProjectFiles &f1, const QmakeProjectFiles &f2)
|
2008-12-02 12:01:29 +01:00
|
|
|
{ return !f1.equals(f2); }
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QDebug operator<<(QDebug d, const QmakeProjectFiles &f)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
QDebug nsp = d.nospace();
|
2013-10-29 14:22:31 +01:00
|
|
|
nsp << "QmakeProjectFiles: proFiles=" << f.proFiles << '\n';
|
2008-12-02 12:01:29 +01:00
|
|
|
for (int i = 0; i < FileTypeSize; ++i)
|
|
|
|
nsp << "Type " << i << " files=" << f.files[i] << " generated=" << f.generatedFiles[i] << '\n';
|
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
// A visitor to collect all files of a project in a QmakeProjectFiles struct
|
2015-02-01 18:44:47 +02:00
|
|
|
class ProjectFilesVisitor : public NodesVisitor
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
ProjectFilesVisitor(QmakeProjectFiles *files);
|
2011-07-13 18:02:35 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
public:
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
static void findProjectFiles(QmakeProFileNode *rootNode, QmakeProjectFiles *files);
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
void visitProjectNode(ProjectNode *projectNode);
|
|
|
|
void visitFolderNode(FolderNode *folderNode);
|
|
|
|
|
|
|
|
private:
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProjectFiles *m_files;
|
2008-12-02 12:01:29 +01:00
|
|
|
};
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
ProjectFilesVisitor::ProjectFilesVisitor(QmakeProjectFiles *files) :
|
2008-12-02 12:01:29 +01:00
|
|
|
m_files(files)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-09-04 16:09:41 +02:00
|
|
|
namespace {
|
|
|
|
// uses std::unique, so takes a sorted list
|
|
|
|
void unique(QStringList &list)
|
|
|
|
{
|
|
|
|
list.erase(std::unique(list.begin(), list.end()), list.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void ProjectFilesVisitor::findProjectFiles(QmakeProFileNode *rootNode, QmakeProjectFiles *files)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
files->clear();
|
|
|
|
ProjectFilesVisitor visitor(files);
|
|
|
|
rootNode->accept(&visitor);
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(files->files[i]);
|
2014-09-04 16:09:41 +02:00
|
|
|
unique(files->files[i]);
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(files->generatedFiles[i]);
|
2014-09-04 16:09:41 +02:00
|
|
|
unique(files->generatedFiles[i]);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2014-06-16 18:25:52 +04:00
|
|
|
Utils::sort(files->proFiles);
|
2014-09-04 16:09:41 +02:00
|
|
|
unique(files->proFiles);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectFilesVisitor::visitProjectNode(ProjectNode *projectNode)
|
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
m_files->proFiles.append(projectNode->filePath().toString());
|
2008-12-02 12:01:29 +01:00
|
|
|
visitFolderNode(projectNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectFilesVisitor::visitFolderNode(FolderNode *folderNode)
|
|
|
|
{
|
2015-01-09 15:50:06 +01:00
|
|
|
if (dynamic_cast<ResourceEditor::ResourceTopLevelNode *>(folderNode))
|
2015-10-29 17:53:47 +01:00
|
|
|
m_files->files[ResourceType].push_back(folderNode->filePath().toString());
|
2014-06-06 15:34:38 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
foreach (FileNode *fileNode, folderNode->fileNodes()) {
|
|
|
|
const int type = fileNode->fileType();
|
|
|
|
QStringList &targetList = fileNode->isGenerated() ? m_files->generatedFiles[type] : m_files->files[type];
|
2015-10-29 17:53:47 +01:00
|
|
|
targetList.push_back(fileNode->filePath().toString());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
// ----------- QmakeProjectFile
|
2011-08-18 16:55:45 +02:00
|
|
|
namespace Internal {
|
2016-01-08 11:09:37 +01:00
|
|
|
QmakeProjectFile::QmakeProjectFile(const QString &filePath)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-03-05 15:58:12 +01:00
|
|
|
setId("Qmake.ProFile");
|
2014-06-26 02:15:34 +02:00
|
|
|
setMimeType(QLatin1String(QmakeProjectManager::Constants::PROFILE_MIMETYPE));
|
2015-02-01 18:44:47 +02:00
|
|
|
setFilePath(FileName::fromString(filePath));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
Core::IDocument::ReloadBehavior QmakeProjectFile::reloadBehavior(ChangeTrigger state, ChangeType type) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(state)
|
|
|
|
Q_UNUSED(type)
|
|
|
|
return BehaviorSilent;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
|
2010-03-19 10:28:05 +01:00
|
|
|
{
|
2011-04-04 15:24:13 +02:00
|
|
|
Q_UNUSED(errorString)
|
2010-03-19 10:28:05 +01:00
|
|
|
Q_UNUSED(flag)
|
|
|
|
Q_UNUSED(type)
|
2011-04-04 15:24:13 +02:00
|
|
|
return true;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2011-08-18 16:46:44 +02:00
|
|
|
} // namespace Internal
|
2012-07-17 15:56:43 +02:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
/*!
|
2013-10-29 14:22:31 +01:00
|
|
|
\class QmakeProject
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProject manages information about an individual Qt 4 (.pro) project file.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
2013-10-29 15:15:10 +01:00
|
|
|
QmakeProject::QmakeProject(QmakeManager *manager, const QString &fileName) :
|
2013-10-29 14:22:31 +01:00
|
|
|
m_projectFiles(new QmakeProjectFiles),
|
2015-06-18 15:14:06 +02:00
|
|
|
m_qmakeVfs(new QMakeVfs)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-10-30 13:34:46 +01:00
|
|
|
setId(Constants::QMAKEPROJECT_ID);
|
2016-01-08 11:31:06 +01:00
|
|
|
setProjectManager(manager);
|
2016-01-08 11:09:37 +01:00
|
|
|
setDocument(new QmakeProjectFile(fileName));
|
2013-10-16 11:02:37 +02:00
|
|
|
setProjectContext(Core::Context(QmakeProjectManager::Constants::PROJECT_ID));
|
2013-05-28 13:19:32 +02:00
|
|
|
setProjectLanguages(Core::Context(ProjectExplorer::Constants::LANG_CXX));
|
2014-07-23 09:09:20 +02:00
|
|
|
setRequiredKitMatcher(QtSupport::QtKitInformation::qtVersionMatcher());
|
2011-04-12 12:17:19 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateTimer.setSingleShot(true);
|
2014-10-24 12:43:14 +02:00
|
|
|
m_asyncUpdateTimer.setInterval(3000);
|
2016-01-07 18:01:04 +01:00
|
|
|
connect(&m_asyncUpdateTimer, &QTimer::timeout, this, &QmakeProject::asyncUpdate);
|
2013-05-29 20:18:51 +02:00
|
|
|
|
2016-02-02 12:44:42 +01:00
|
|
|
setRootProjectNode(new QmakeProFileNode(this, projectFilePath()));
|
|
|
|
|
2016-01-07 18:01:04 +01:00
|
|
|
connect(BuildManager::instance(), &BuildManager::buildQueueFinished,
|
|
|
|
this, &QmakeProject::buildFinished);
|
2014-10-20 17:23:07 +02:00
|
|
|
|
|
|
|
setPreferredKitMatcher(KitMatcher([this](const Kit *kit) -> bool {
|
|
|
|
return matchesKit(kit);
|
|
|
|
}));
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProject::~QmakeProject()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-10-05 08:31:16 +02:00
|
|
|
delete m_projectImporter;
|
|
|
|
m_projectImporter = nullptr;
|
2010-04-22 18:57:43 +02:00
|
|
|
m_codeModelFuture.cancel();
|
2010-03-11 17:01:06 +01:00
|
|
|
m_asyncUpdateState = ShuttingDown;
|
2016-04-04 11:27:19 +02:00
|
|
|
|
|
|
|
// Make sure root node (and associated readers) are shut hown before proceeding
|
|
|
|
setRootProjectNode(nullptr);
|
|
|
|
|
2016-01-08 11:31:06 +01:00
|
|
|
projectManager()->unregisterProject(this);
|
2008-12-02 12:01:29 +01:00
|
|
|
delete m_projectFiles;
|
2010-03-11 17:01:06 +01:00
|
|
|
m_cancelEvaluate = true;
|
2014-09-10 12:53:13 +02:00
|
|
|
Q_ASSERT(m_qmakeGlobalsRefCnt == 0);
|
2014-11-20 12:26:23 +01:00
|
|
|
delete m_qmakeVfs;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateFileList()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
QmakeProjectFiles newFiles;
|
2016-01-08 12:49:00 +01:00
|
|
|
ProjectFilesVisitor::findProjectFiles(rootProjectNode(), &newFiles);
|
2008-12-02 12:01:29 +01:00
|
|
|
if (newFiles != *m_projectFiles) {
|
|
|
|
*m_projectFiles = newFiles;
|
|
|
|
emit fileListChanged();
|
|
|
|
if (debug)
|
|
|
|
qDebug() << Q_FUNC_INFO << *m_projectFiles;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-18 16:57:29 +02:00
|
|
|
Project::RestoreResult QmakeProject::fromMap(const QVariantMap &map, QString *errorMessage)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-05-18 16:57:29 +02:00
|
|
|
RestoreResult result = Project::fromMap(map, errorMessage);
|
|
|
|
if (result != RestoreResult::Ok)
|
|
|
|
return result;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2010-02-08 15:50:06 +01:00
|
|
|
// Prune targets without buildconfigurations:
|
|
|
|
// This can happen esp. when updating from a old version of Qt Creator
|
2010-12-06 16:24:29 +01:00
|
|
|
QList<Target *>ts = targets();
|
2010-02-08 15:50:06 +01:00
|
|
|
foreach (Target *t, ts) {
|
2010-02-18 18:37:11 +01:00
|
|
|
if (t->buildConfigurations().isEmpty()) {
|
2012-03-15 17:17:40 +01:00
|
|
|
qWarning() << "Removing" << t->id().name() << "since it has no buildconfigurations!";
|
2010-02-08 15:50:06 +01:00
|
|
|
removeTarget(t);
|
2010-02-18 18:37:11 +01:00
|
|
|
}
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
2016-01-08 11:31:06 +01:00
|
|
|
projectManager()->registerProject(this);
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2012-07-17 15:56:43 +02:00
|
|
|
// On active buildconfiguration changes, reevaluate the .pro files
|
|
|
|
m_activeTarget = activeTarget();
|
2015-02-01 18:44:47 +02:00
|
|
|
if (m_activeTarget) {
|
|
|
|
connect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
|
|
|
this, &QmakeProject::scheduleAsyncUpdateLater);
|
|
|
|
}
|
2012-07-17 15:56:43 +02:00
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
connect(this, &Project::activeTargetChanged,
|
|
|
|
this, &QmakeProject::activeTargetWasChanged);
|
2010-02-08 15:50:06 +01:00
|
|
|
|
2014-10-24 12:43:14 +02:00
|
|
|
scheduleAsyncUpdate(QmakeProFileNode::ParseNow);
|
2015-05-18 16:57:29 +02:00
|
|
|
return RestoreResult::Ok;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
/// equalFileList compares two file lists ignoring
|
|
|
|
/// <configuration> without generating temporary lists
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProject::equalFileList(const QStringList &a, const QStringList &b)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
if (abs(a.length() - b.length()) > 1)
|
|
|
|
return false;
|
|
|
|
QStringList::const_iterator ait = a.constBegin();
|
|
|
|
QStringList::const_iterator bit = b.constBegin();
|
|
|
|
QStringList::const_iterator aend = a.constEnd();
|
|
|
|
QStringList::const_iterator bend = b.constEnd();
|
|
|
|
|
|
|
|
while (ait != aend && bit != bend) {
|
2014-09-15 00:12:27 +02:00
|
|
|
if (*ait == CppTools::CppModelManager::configurationFileName())
|
2010-03-10 16:55:37 +01:00
|
|
|
++ait;
|
2014-09-15 00:12:27 +02:00
|
|
|
else if (*bit == CppTools::CppModelManager::configurationFileName())
|
2010-03-10 16:55:37 +01:00
|
|
|
++bit;
|
|
|
|
else if (*ait == *bit)
|
|
|
|
++ait, ++bit;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return (ait == aend && bit == bend);
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateCodeModels()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
if (debug)
|
2013-10-29 14:22:31 +01:00
|
|
|
qDebug() << "QmakeProject::updateCodeModel()";
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2011-10-28 10:15:04 +00:00
|
|
|
if (activeTarget() && !activeTarget()->activeBuildConfiguration())
|
2010-02-08 15:50:06 +01:00
|
|
|
return;
|
|
|
|
|
2010-09-21 14:28:55 +02:00
|
|
|
updateCppCodeModel();
|
|
|
|
updateQmlJSCodeModel();
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateCppCodeModel()
|
2010-09-21 14:28:55 +02:00
|
|
|
{
|
2016-09-23 15:53:31 +02:00
|
|
|
m_toolChainWarnings.clear();
|
|
|
|
|
2013-04-02 11:28:11 +02:00
|
|
|
typedef CppTools::ProjectPart ProjectPart;
|
|
|
|
typedef CppTools::ProjectFile ProjectFile;
|
2012-02-16 15:09:56 +01:00
|
|
|
|
2016-04-04 11:26:30 +02:00
|
|
|
Kit *k = nullptr;
|
2015-02-01 18:44:47 +02:00
|
|
|
if (Target *target = activeTarget())
|
2012-09-03 18:31:44 +02:00
|
|
|
k = target->kit();
|
2012-04-24 15:49:09 +02:00
|
|
|
else
|
2013-08-21 12:48:46 +02:00
|
|
|
k = KitManager::defaultKit();
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-15 23:13:28 +02:00
|
|
|
CppTools::CppModelManager *modelmanager = CppTools::CppModelManager::instance();
|
2013-10-29 14:22:31 +01:00
|
|
|
FindQmakeProFiles findQmakeProFiles;
|
|
|
|
QList<QmakeProFileNode *> proFiles = findQmakeProFiles(rootProjectNode());
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-02-15 23:13:28 +02:00
|
|
|
CppTools::ProjectInfo pinfo(this);
|
2014-11-20 12:50:37 +01:00
|
|
|
|
2015-02-15 23:13:28 +02:00
|
|
|
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
|
2012-02-16 15:09:56 +01:00
|
|
|
ProjectPart::QtVersion qtVersionForPart = ProjectPart::NoQt;
|
|
|
|
if (qtVersion) {
|
|
|
|
if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
|
|
|
|
qtVersionForPart = ProjectPart::Qt4;
|
|
|
|
else
|
|
|
|
qtVersionForPart = ProjectPart::Qt5;
|
|
|
|
}
|
2010-10-18 17:12:44 +02:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
QList<ProjectExplorer::ExtraCompiler *> generators;
|
2013-10-29 14:22:31 +01:00
|
|
|
foreach (QmakeProFileNode *pro, proFiles) {
|
2016-09-23 15:53:31 +02:00
|
|
|
warnOnToolChainMismatch(pro);
|
|
|
|
|
2014-08-19 12:01:08 +02:00
|
|
|
ProjectPart::Ptr templatePart(new ProjectPart);
|
|
|
|
templatePart->project = this;
|
|
|
|
templatePart->displayName = pro->displayName();
|
2015-10-29 17:53:47 +01:00
|
|
|
templatePart->projectFile = pro->filePath().toString();
|
2014-11-03 14:54:31 +01:00
|
|
|
templatePart->selectedForBuilding = pro->includedInExactParse();
|
2012-12-08 23:38:26 +04:00
|
|
|
|
|
|
|
if (pro->variableValue(ConfigVar).contains(QLatin1String("qt")))
|
2014-08-19 12:01:08 +02:00
|
|
|
templatePart->qtVersion = qtVersionForPart;
|
2012-12-08 23:38:26 +04:00
|
|
|
else
|
2014-08-19 12:01:08 +02:00
|
|
|
templatePart->qtVersion = ProjectPart::NoQt;
|
2011-02-01 18:36:00 +01:00
|
|
|
|
2012-02-16 15:09:56 +01:00
|
|
|
// part->defines
|
2014-08-19 12:01:08 +02:00
|
|
|
templatePart->projectDefines += pro->cxxDefines();
|
2012-02-16 15:09:56 +01:00
|
|
|
|
2015-02-04 10:18:48 +01:00
|
|
|
foreach (const QString &inc, pro->variableValue(IncludePathVar)) {
|
|
|
|
const auto headerPath
|
2016-01-13 14:12:15 +01:00
|
|
|
= CppTools::ProjectPartHeaderPath(inc, CppTools::ProjectPartHeaderPath::IncludePath);
|
2015-02-04 10:18:48 +01:00
|
|
|
if (!templatePart->headerPaths.contains(headerPath))
|
|
|
|
templatePart->headerPaths += headerPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qtVersion) {
|
2014-06-25 17:23:19 +02:00
|
|
|
if (!qtVersion->frameworkInstallPath().isEmpty()) {
|
2016-01-13 14:12:15 +01:00
|
|
|
templatePart->headerPaths += CppTools::ProjectPartHeaderPath(
|
2014-06-25 17:23:19 +02:00
|
|
|
qtVersion->frameworkInstallPath(),
|
2016-01-13 14:12:15 +01:00
|
|
|
CppTools::ProjectPartHeaderPath::FrameworkPath);
|
2013-04-28 16:59:44 +04:00
|
|
|
}
|
2009-05-04 18:22:40 +02:00
|
|
|
}
|
2013-04-28 16:59:44 +04:00
|
|
|
|
2012-02-16 15:09:56 +01:00
|
|
|
// part->precompiledHeaders
|
2014-08-19 12:01:08 +02:00
|
|
|
templatePart->precompiledHeaders.append(pro->variableValue(PrecompiledHeaderVar));
|
|
|
|
|
unify {,obj}c++{source,header} handling in qmake project manager
consistently with Xcode, qmake nowadays knows only one SOURCES list,
which is automatically classified by extension.
to replicate that, we actually copy the objective_c.prf file from qt
5.6.3 and use it to override whatever comes with qt, so we can treat all
qt versions uniformly.
also, the code model throws away the information which files were listed
as sources and which as headers. this is technically incorrect, as a
source may be only included rather than compiled, but there is no point
in extracting information which is not used.
conclusion: lump all c-like sources into one variable as far as project
processing is concerned.
and as far as configuration goes, our code model doesn't differentiate
anyway, so the duplicated setup paths can be eliminated as well.
Change-Id: I24b1bc056f8d9eb579c9378817f602912ab49971
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2016-10-25 16:28:40 +02:00
|
|
|
// TODO: there is no LANG_OBJCXX, so:
|
|
|
|
const QStringList cxxflags = pro->variableValue(CppFlagsVar);
|
|
|
|
CppTools::ProjectPartBuilder::evaluateProjectPartToolchain(
|
|
|
|
templatePart.data(), ToolChainKitInformation::toolChain(k, ToolChain::Language::Cxx),
|
|
|
|
cxxflags, SysRootKitInformation::sysRoot(k));
|
|
|
|
setProjectLanguage(ProjectExplorer::Constants::LANG_CXX, true);
|
2015-02-15 23:43:26 +02:00
|
|
|
|
2014-08-19 12:01:08 +02:00
|
|
|
ProjectPart::Ptr cppPart = templatePart->copy();
|
|
|
|
ProjectPart::Ptr objcppPart = templatePart->copy();
|
unify {,obj}c++{source,header} handling in qmake project manager
consistently with Xcode, qmake nowadays knows only one SOURCES list,
which is automatically classified by extension.
to replicate that, we actually copy the objective_c.prf file from qt
5.6.3 and use it to override whatever comes with qt, so we can treat all
qt versions uniformly.
also, the code model throws away the information which files were listed
as sources and which as headers. this is technically incorrect, as a
source may be only included rather than compiled, but there is no point
in extracting information which is not used.
conclusion: lump all c-like sources into one variable as far as project
processing is concerned.
and as far as configuration goes, our code model doesn't differentiate
anyway, so the duplicated setup paths can be eliminated as well.
Change-Id: I24b1bc056f8d9eb579c9378817f602912ab49971
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2016-10-25 16:28:40 +02:00
|
|
|
foreach (const QString &file, pro->variableValue(SourceVar)) {
|
|
|
|
ProjectFile::Kind kind = ProjectFile::classify(file);
|
|
|
|
switch (kind) {
|
|
|
|
case ProjectFile::ObjCHeader:
|
|
|
|
case ProjectFile::ObjCSource:
|
|
|
|
case ProjectFile::ObjCXXHeader:
|
|
|
|
case ProjectFile::ObjCXXSource:
|
|
|
|
objcppPart->files << ProjectFile(file, kind);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cppPart->files << ProjectFile(file, kind);
|
|
|
|
break;
|
2014-08-19 12:01:08 +02:00
|
|
|
}
|
|
|
|
}
|
2012-02-16 15:09:56 +01:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
// generated files:
|
|
|
|
QList<ProjectExplorer::ExtraCompiler *> proGenerators = pro->extraCompilers();
|
|
|
|
foreach (ProjectExplorer::ExtraCompiler *ec, proGenerators) {
|
2016-03-11 15:18:20 +02:00
|
|
|
ec->forEachTarget([&](const Utils::FileName &generatedFile) {
|
2016-01-15 16:12:54 +01:00
|
|
|
QString name = generatedFile.toString();
|
|
|
|
ProjectFile::Kind kind = ProjectFile::classify(name);
|
|
|
|
switch (kind) {
|
|
|
|
case ProjectFile::CHeader:
|
|
|
|
case ProjectFile::CSource:
|
|
|
|
case ProjectFile::CXXHeader:
|
|
|
|
case ProjectFile::CXXSource:
|
|
|
|
cppPart->files << ProjectFile(name, kind);
|
|
|
|
break;
|
|
|
|
case ProjectFile::ObjCHeader:
|
|
|
|
case ProjectFile::ObjCSource:
|
|
|
|
case ProjectFile::ObjCXXHeader:
|
|
|
|
case ProjectFile::ObjCXXSource:
|
|
|
|
objcppPart->files << ProjectFile(name, kind);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2016-03-11 15:18:20 +02:00
|
|
|
});
|
2016-01-15 16:12:54 +01:00
|
|
|
}
|
|
|
|
generators.append(proGenerators);
|
|
|
|
|
|
|
|
cppPart->files.prepend(ProjectFile(CppTools::CppModelManager::configurationFileName(),
|
|
|
|
ProjectFile::CXXSource));
|
unify {,obj}c++{source,header} handling in qmake project manager
consistently with Xcode, qmake nowadays knows only one SOURCES list,
which is automatically classified by extension.
to replicate that, we actually copy the objective_c.prf file from qt
5.6.3 and use it to override whatever comes with qt, so we can treat all
qt versions uniformly.
also, the code model throws away the information which files were listed
as sources and which as headers. this is technically incorrect, as a
source may be only included rather than compiled, but there is no point
in extracting information which is not used.
conclusion: lump all c-like sources into one variable as far as project
processing is concerned.
and as far as configuration goes, our code model doesn't differentiate
anyway, so the duplicated setup paths can be eliminated as well.
Change-Id: I24b1bc056f8d9eb579c9378817f602912ab49971
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2016-10-25 16:28:40 +02:00
|
|
|
pinfo.appendProjectPart(cppPart);
|
|
|
|
objcppPart->displayName += QLatin1String(" (ObjC++)");
|
|
|
|
if (!objcppPart->files.isEmpty()) {
|
|
|
|
pinfo.appendProjectPart(objcppPart);
|
2014-08-19 12:01:08 +02:00
|
|
|
cppPart->displayName += QLatin1String(" (C++)");
|
unify {,obj}c++{source,header} handling in qmake project manager
consistently with Xcode, qmake nowadays knows only one SOURCES list,
which is automatically classified by extension.
to replicate that, we actually copy the objective_c.prf file from qt
5.6.3 and use it to override whatever comes with qt, so we can treat all
qt versions uniformly.
also, the code model throws away the information which files were listed
as sources and which as headers. this is technically incorrect, as a
source may be only included rather than compiled, but there is no point
in extracting information which is not used.
conclusion: lump all c-like sources into one variable as far as project
processing is concerned.
and as far as configuration goes, our code model doesn't differentiate
anyway, so the duplicated setup paths can be eliminated as well.
Change-Id: I24b1bc056f8d9eb579c9378817f602912ab49971
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
2016-10-25 16:28:40 +02:00
|
|
|
}
|
2014-08-19 12:01:08 +02:00
|
|
|
}
|
2014-09-12 14:14:18 +02:00
|
|
|
pinfo.finish();
|
2013-04-10 14:45:47 +02:00
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
// Also update Code Model Support for generated files:
|
|
|
|
CppTools::GeneratedCodeModelSupport::update(generators);
|
2013-07-11 16:24:51 +02:00
|
|
|
|
2013-07-16 12:08:39 +02:00
|
|
|
m_codeModelFuture = modelmanager->updateProjectInfo(pinfo);
|
2009-05-04 18:22:40 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateQmlJSCodeModel()
|
2010-09-21 14:28:55 +02:00
|
|
|
{
|
2010-09-27 11:16:43 +01:00
|
|
|
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
2010-09-21 14:28:55 +02:00
|
|
|
if (!modelManager)
|
|
|
|
return;
|
|
|
|
|
2012-12-06 17:20:58 +01:00
|
|
|
QmlJS::ModelManagerInterface::ProjectInfo projectInfo =
|
2014-07-24 11:48:30 +02:00
|
|
|
modelManager->defaultProjectInfoForProject(this);
|
2010-09-21 14:28:55 +02:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
FindQmakeProFiles findQt4ProFiles;
|
|
|
|
QList<QmakeProFileNode *> proFiles = findQt4ProFiles(rootProjectNode());
|
2010-09-21 14:28:55 +02:00
|
|
|
|
2011-06-23 15:09:38 +02:00
|
|
|
projectInfo.importPaths.clear();
|
2012-11-21 16:18:53 +01:00
|
|
|
|
|
|
|
bool hasQmlLib = false;
|
2013-10-29 14:22:31 +01:00
|
|
|
foreach (QmakeProFileNode *node, proFiles) {
|
2014-07-22 19:06:44 +02:00
|
|
|
foreach (const QString &path, node->variableValue(QmlImportPathVar))
|
2015-02-01 18:44:47 +02:00
|
|
|
projectInfo.importPaths.maybeInsert(FileName::fromString(path),
|
2014-07-22 19:06:44 +02:00
|
|
|
QmlJS::Dialect::Qml);
|
2016-10-27 16:36:06 +02:00
|
|
|
const QStringList &exactResources = node->variableValue(ExactResourceVar);
|
|
|
|
const QStringList &cumulativeResources = node->variableValue(CumulativeResourceVar);
|
|
|
|
projectInfo.activeResourceFiles.append(exactResources);
|
|
|
|
projectInfo.allResourceFiles.append(exactResources);
|
|
|
|
projectInfo.allResourceFiles.append(cumulativeResources);
|
|
|
|
foreach (const QString &rc, exactResources) {
|
2016-10-24 19:30:24 +02:00
|
|
|
QString contents;
|
2016-10-27 16:36:06 +02:00
|
|
|
if (m_qmakeVfs->readVirtualFile(rc, QMakeVfs::VfsExact, &contents))
|
|
|
|
projectInfo.resourceFileContents[rc] = contents;
|
|
|
|
}
|
|
|
|
foreach (const QString &rc, cumulativeResources) {
|
|
|
|
QString contents;
|
|
|
|
if (m_qmakeVfs->readVirtualFile(rc, QMakeVfs::VfsCumulative, &contents))
|
2016-10-24 19:30:24 +02:00
|
|
|
projectInfo.resourceFileContents[rc] = contents;
|
|
|
|
}
|
2012-11-21 16:18:53 +01:00
|
|
|
if (!hasQmlLib) {
|
|
|
|
QStringList qtLibs = node->variableValue(QtVar);
|
|
|
|
hasQmlLib = qtLibs.contains(QLatin1String("declarative")) ||
|
|
|
|
qtLibs.contains(QLatin1String("qml")) ||
|
|
|
|
qtLibs.contains(QLatin1String("quick"));
|
|
|
|
}
|
2010-09-21 14:28:55 +02:00
|
|
|
}
|
2011-09-21 15:54:07 +02:00
|
|
|
|
2013-05-28 13:19:32 +02:00
|
|
|
// If the project directory has a pro/pri file that includes a qml or quick or declarative
|
|
|
|
// library then chances of the project being a QML project is quite high.
|
|
|
|
// This assumption fails when there are no QDeclarativeEngine/QDeclarativeView (QtQuick 1)
|
|
|
|
// or QQmlEngine/QQuickView (QtQuick 2) instances.
|
|
|
|
if (hasQmlLib)
|
2014-11-13 12:31:47 +01:00
|
|
|
addProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS);
|
2013-05-28 13:19:32 +02:00
|
|
|
|
2013-05-21 11:35:15 +02:00
|
|
|
projectInfo.activeResourceFiles.removeDuplicates();
|
|
|
|
projectInfo.allResourceFiles.removeDuplicates();
|
2010-09-21 14:28:55 +02:00
|
|
|
|
2014-01-23 14:28:31 +01:00
|
|
|
modelManager->updateProjectInfo(projectInfo, this);
|
2010-09-21 14:28:55 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateRunConfigurations()
|
2012-07-17 15:56:43 +02:00
|
|
|
{
|
2013-06-19 12:17:59 +02:00
|
|
|
if (activeTarget())
|
|
|
|
activeTarget()->updateDefaultRunConfigurations();
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
2014-10-24 12:43:14 +02:00
|
|
|
void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode *node, QmakeProFileNode::AsyncUpdateDelay delay)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2010-10-25 17:26:41 +02:00
|
|
|
if (m_asyncUpdateState == ShuttingDown)
|
|
|
|
return;
|
2010-10-27 16:27:22 +02:00
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
2015-10-29 17:53:47 +01:00
|
|
|
qDebug()<<"schduleAsyncUpdate (node)"<<node->filePath();
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
if (m_cancelEvaluate) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Already canceling, nothing to do";
|
2010-03-10 16:55:37 +01:00
|
|
|
// A cancel is in progress
|
|
|
|
// That implies that a full update is going to happen afterwards
|
|
|
|
// So we don't need to do anything
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-02 12:10:18 +01:00
|
|
|
node->setParseInProgressRecursive(true);
|
|
|
|
setAllBuildConfigurationsEnabled(false);
|
2011-01-19 15:46:01 +01:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending) {
|
|
|
|
// Just postpone
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" full update pending, restarting timer";
|
2014-10-24 12:43:14 +02:00
|
|
|
startAsyncTimer(delay);
|
2010-03-10 16:55:37 +01:00
|
|
|
} else if (m_asyncUpdateState == AsyncPartialUpdatePending
|
|
|
|
|| m_asyncUpdateState == Base) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" adding node to async update list, setting state to AsyncPartialUpdatePending";
|
2010-03-10 16:55:37 +01:00
|
|
|
// Add the node
|
|
|
|
m_asyncUpdateState = AsyncPartialUpdatePending;
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakeProFileNode *>::iterator it;
|
2010-03-10 16:55:37 +01:00
|
|
|
bool add = true;
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"scheduleAsyncUpdate();"<<m_partialEvaluate.size()<<"nodes";
|
2010-03-10 16:55:37 +01:00
|
|
|
it = m_partialEvaluate.begin();
|
|
|
|
while (it != m_partialEvaluate.end()) {
|
|
|
|
if (*it == node) {
|
|
|
|
add = false;
|
|
|
|
break;
|
|
|
|
} else if (node->isParent(*it)) { // We already have the parent in the list, nothing to do
|
2011-09-12 12:40:53 +02:00
|
|
|
it = m_partialEvaluate.erase(it);
|
|
|
|
} else if ((*it)->isParent(node)) { // The node is the parent of a child already in the list
|
2010-03-10 16:55:37 +01:00
|
|
|
add = false;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (add)
|
|
|
|
m_partialEvaluate.append(node);
|
2012-09-04 11:02:11 +02:00
|
|
|
|
|
|
|
// Cancel running code model update
|
|
|
|
m_codeModelFuture.cancel();
|
2014-10-24 12:43:14 +02:00
|
|
|
|
|
|
|
startAsyncTimer(delay);
|
2010-03-10 16:55:37 +01:00
|
|
|
} else if (m_asyncUpdateState == AsyncUpdateInProgress) {
|
|
|
|
// A update is in progress
|
|
|
|
// And this slot only gets called if a file changed on disc
|
|
|
|
// So we'll play it safe and schedule a complete evaluate
|
|
|
|
// This might trigger if due to version control a few files
|
|
|
|
// change a partial update gets in progress and then another
|
|
|
|
// batch of changes come in, which triggers a full update
|
|
|
|
// even if that's not really needed
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Async update in progress, scheduling new one afterwards";
|
2014-10-24 12:43:14 +02:00
|
|
|
scheduleAsyncUpdate(delay);
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-24 12:43:14 +02:00
|
|
|
void QmakeProject::scheduleAsyncUpdate(QmakeProFileNode::AsyncUpdateDelay delay)
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"scheduleAsyncUpdate";
|
2010-10-25 17:26:41 +02:00
|
|
|
if (m_asyncUpdateState == ShuttingDown)
|
|
|
|
return;
|
2010-10-27 16:27:22 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
if (m_cancelEvaluate) { // we are in progress of canceling
|
|
|
|
// and will start the evaluation after that
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" canceling is in progress, doing nothing";
|
2010-03-10 16:55:37 +01:00
|
|
|
return;
|
|
|
|
}
|
2016-11-02 12:10:18 +01:00
|
|
|
|
|
|
|
rootProjectNode()->setParseInProgressRecursive(true);
|
|
|
|
setAllBuildConfigurationsEnabled(false);
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
if (m_asyncUpdateState == AsyncUpdateInProgress) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" update in progress, canceling and setting state to full update pending";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_cancelEvaluate = true;
|
|
|
|
m_asyncUpdateState = AsyncFullUpdatePending;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" starting timer for full update, setting state to full update pending";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_partialEvaluate.clear();
|
|
|
|
m_asyncUpdateState = AsyncFullUpdatePending;
|
2010-04-22 18:57:43 +02:00
|
|
|
|
|
|
|
// Cancel running code model update
|
|
|
|
m_codeModelFuture.cancel();
|
2014-10-24 12:43:14 +02:00
|
|
|
startAsyncTimer(delay);
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
|
2014-10-24 12:43:14 +02:00
|
|
|
void QmakeProject::startAsyncTimer(QmakeProFileNode::AsyncUpdateDelay delay)
|
|
|
|
{
|
|
|
|
m_asyncUpdateTimer.stop();
|
|
|
|
m_asyncUpdateTimer.setInterval(qMin(m_asyncUpdateTimer.interval(), delay == QmakeProFileNode::ParseLater ? 3000 : 0));
|
|
|
|
m_asyncUpdateTimer.start();
|
|
|
|
}
|
2010-03-10 16:55:37 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::incrementPendingEvaluateFutures()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
++m_pendingEvaluateFuturesCount;
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"incrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->setProgressRange(m_asyncUpdateFutureInterface->progressMinimum(),
|
|
|
|
m_asyncUpdateFutureInterface->progressMaximum() + 1);
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::decrementPendingEvaluateFutures()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
--m_pendingEvaluateFuturesCount;
|
|
|
|
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"decrementPendingEvaluateFutures to"<<m_pendingEvaluateFuturesCount;
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->setProgressValue(m_asyncUpdateFutureInterface->progressValue() + 1);
|
|
|
|
if (m_pendingEvaluateFuturesCount == 0) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" WOHOO, no pending futures, cleaning up";
|
2010-03-10 16:55:37 +01:00
|
|
|
// We are done!
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" reporting finished";
|
2012-10-08 14:33:33 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateFutureInterface->reportFinished();
|
|
|
|
delete m_asyncUpdateFutureInterface;
|
2016-04-04 11:26:30 +02:00
|
|
|
m_asyncUpdateFutureInterface = nullptr;
|
2010-03-10 16:55:37 +01:00
|
|
|
m_cancelEvaluate = false;
|
|
|
|
|
|
|
|
// TODO clear the profile cache ?
|
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending || m_asyncUpdateState == AsyncPartialUpdatePending) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Oh update is pending start the timer";
|
2016-11-02 12:10:18 +01:00
|
|
|
rootProjectNode()->setParseInProgressRecursive(true);
|
|
|
|
setAllBuildConfigurationsEnabled(false);
|
2014-10-24 12:43:14 +02:00
|
|
|
startAsyncTimer(QmakeProFileNode::ParseLater);
|
2010-03-11 17:01:06 +01:00
|
|
|
} else if (m_asyncUpdateState != ShuttingDown){
|
2010-10-30 21:54:23 +02:00
|
|
|
// After being done, we need to call:
|
2016-11-02 12:10:18 +01:00
|
|
|
setAllBuildConfigurationsEnabled(true);
|
|
|
|
|
2011-09-12 13:25:12 +02:00
|
|
|
m_asyncUpdateState = Base;
|
2010-03-11 17:01:06 +01:00
|
|
|
updateFileList();
|
2011-09-15 12:15:10 +02:00
|
|
|
updateCodeModels();
|
2012-08-20 12:41:52 +02:00
|
|
|
updateBuildSystemData();
|
2014-09-26 15:24:02 +02:00
|
|
|
if (activeTarget())
|
|
|
|
activeTarget()->updateDefaultDeployConfigurations();
|
2012-07-17 15:56:43 +02:00
|
|
|
updateRunConfigurations();
|
|
|
|
emit proFilesEvaluated();
|
2016-10-20 13:18:54 +02:00
|
|
|
emit parsingFinished();
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Setting state to Base";
|
2010-03-10 16:55:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProject::wasEvaluateCanceled()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
|
|
|
return m_cancelEvaluate;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::asyncUpdate()
|
2010-03-10 16:55:37 +01:00
|
|
|
{
|
2014-10-13 16:26:10 +02:00
|
|
|
m_asyncUpdateTimer.setInterval(3000);
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<"async update, timer expired, doing now";
|
2013-05-29 20:18:51 +02:00
|
|
|
|
|
|
|
m_qmakeVfs->invalidateCache();
|
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
Q_ASSERT(!m_asyncUpdateFutureInterface);
|
|
|
|
m_asyncUpdateFutureInterface = new QFutureInterface<void>();
|
|
|
|
|
2010-04-13 16:32:01 +02:00
|
|
|
m_asyncUpdateFutureInterface->setProgressRange(0, 0);
|
2014-04-17 15:14:14 +02:00
|
|
|
Core::ProgressManager::addTask(m_asyncUpdateFutureInterface->future(),
|
|
|
|
tr("Reading Project \"%1\"").arg(displayName()),
|
|
|
|
Constants::PROFILE_EVALUATE);
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" adding task";
|
2010-03-10 16:55:37 +01:00
|
|
|
|
|
|
|
m_asyncUpdateFutureInterface->reportStarted();
|
|
|
|
|
|
|
|
if (m_asyncUpdateState == AsyncFullUpdatePending) {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" full update, starting with root node";
|
2016-01-08 12:49:00 +01:00
|
|
|
rootProjectNode()->asyncUpdate();
|
2010-03-10 16:55:37 +01:00
|
|
|
} else {
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" partial update,"<<m_partialEvaluate.size()<<"nodes to update";
|
2013-10-29 14:22:31 +01:00
|
|
|
foreach (QmakeProFileNode *node, m_partialEvaluate)
|
2010-03-10 16:55:37 +01:00
|
|
|
node->asyncUpdate();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_partialEvaluate.clear();
|
2010-03-12 15:12:46 +01:00
|
|
|
if (debug)
|
|
|
|
qDebug()<<" Setting state to AsyncUpdateInProgress";
|
2010-03-10 16:55:37 +01:00
|
|
|
m_asyncUpdateState = AsyncUpdateInProgress;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::buildFinished(bool success)
|
2013-05-29 20:18:51 +02:00
|
|
|
{
|
|
|
|
if (success)
|
|
|
|
m_qmakeVfs->invalidateContents();
|
|
|
|
}
|
|
|
|
|
2016-01-08 11:31:06 +01:00
|
|
|
QmakeManager *QmakeProject::projectManager() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2016-01-08 11:31:06 +01:00
|
|
|
return static_cast<QmakeManager *>(Project::projectManager());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProject::supportsKit(Kit *k, QString *errorMessage) const
|
2012-04-24 15:49:09 +02:00
|
|
|
{
|
2012-09-09 20:41:30 +03:00
|
|
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
|
2012-09-20 11:16:47 +02:00
|
|
|
if (!version && errorMessage)
|
|
|
|
*errorMessage = tr("No Qt version set in kit.");
|
2012-04-24 15:49:09 +02:00
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProject::displayName() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2014-05-02 12:22:58 +02:00
|
|
|
return projectFilePath().toFileInfo().completeBaseName();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QStringList QmakeProject::files(FilesMode fileMode) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
|
|
|
QStringList files;
|
|
|
|
for (int i = 0; i < FileTypeSize; ++i) {
|
2016-01-08 16:56:35 +01:00
|
|
|
if (fileMode & SourceFiles)
|
|
|
|
files += m_projectFiles->files[i];
|
|
|
|
if (fileMode & GeneratedFiles)
|
2008-12-02 12:01:29 +01:00
|
|
|
files += m_projectFiles->generatedFiles[i];
|
|
|
|
}
|
2014-01-23 17:01:43 +01:00
|
|
|
|
|
|
|
files.removeDuplicates();
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
return files;
|
|
|
|
}
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
// Find the folder that contains a file with a certain name (recurse down)
|
|
|
|
static FolderNode *folderOf(FolderNode *in, const FileName &fileName)
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
2012-11-28 20:44:03 +02:00
|
|
|
foreach (FileNode *fn, in->fileNodes())
|
2016-01-15 16:12:54 +01:00
|
|
|
if (fn->filePath() == fileName)
|
2009-12-03 16:23:15 +01:00
|
|
|
return in;
|
2012-11-28 20:44:03 +02:00
|
|
|
foreach (FolderNode *folder, in->subFolderNodes())
|
2016-01-15 16:12:54 +01:00
|
|
|
if (FolderNode *pn = folderOf(folder, fileName))
|
2009-12-03 16:23:15 +01:00
|
|
|
return pn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
// Find the QmakeProFileNode that contains a certain file.
|
2009-12-03 16:23:15 +01:00
|
|
|
// First recurse down to folder, then find the pro-file.
|
2016-01-15 16:12:54 +01:00
|
|
|
static FileNode *fileNodeOf(QmakeProFileNode *in, const FileName &fileName)
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
2016-01-15 16:12:54 +01:00
|
|
|
for (FolderNode *folder = folderOf(in, fileName); folder; folder = folder->parentFolderNode()) {
|
|
|
|
if (QmakeProFileNode *proFile = dynamic_cast<QmakeProFileNode *>(folder)) {
|
|
|
|
foreach (FileNode *fileNode, proFile->fileNodes()) {
|
|
|
|
if (fileNode->filePath() == fileName)
|
|
|
|
return fileNode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-12-03 16:23:15 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-01-15 16:12:54 +01:00
|
|
|
QStringList QmakeProject::filesGeneratedFrom(const QString &input) const
|
2009-12-03 16:23:15 +01:00
|
|
|
{
|
|
|
|
// Look in sub-profiles as SessionManager::projectForFile returns
|
|
|
|
// the top-level project only.
|
2016-01-15 16:12:54 +01:00
|
|
|
if (!rootProjectNode())
|
|
|
|
return QStringList();
|
|
|
|
|
|
|
|
if (const FileNode *file = fileNodeOf(rootProjectNode(), FileName::fromString(input))) {
|
|
|
|
QmakeProFileNode *pro = static_cast<QmakeProFileNode *>(file->parentFolderNode());
|
|
|
|
return pro->generatedFiles(pro->buildDir(), file);
|
|
|
|
} else {
|
|
|
|
return QStringList();
|
|
|
|
}
|
2009-12-03 16:23:15 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::proFileParseError(const QString &errorMessage)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-09-05 01:52:17 +02:00
|
|
|
Core::MessageManager::write(errorMessage);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QtSupport::ProFileReader *QmakeProject::createProFileReader(const QmakeProFileNode *qmakeProFileNode, QmakeBuildConfiguration *bc)
|
2009-12-07 20:49:39 +01:00
|
|
|
{
|
2012-05-02 15:20:08 +02:00
|
|
|
if (!m_qmakeGlobals) {
|
2016-10-21 20:23:07 +02:00
|
|
|
m_qmakeGlobals = new QMakeGlobals;
|
2012-05-02 15:20:08 +02:00
|
|
|
m_qmakeGlobalsRefCnt = 0;
|
2009-12-07 20:49:39 +01:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
Kit *k;
|
2015-02-01 18:44:47 +02:00
|
|
|
Environment env = Environment::systemEnvironment();
|
2011-10-28 10:15:04 +00:00
|
|
|
QStringList qmakeArgs;
|
2012-06-24 20:30:02 +03:00
|
|
|
if (!bc)
|
2013-10-16 14:00:45 +02:00
|
|
|
bc = activeTarget() ? static_cast<QmakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration()) : 0;
|
2012-06-24 20:30:02 +03:00
|
|
|
|
|
|
|
if (bc) {
|
2012-09-03 18:31:44 +02:00
|
|
|
k = bc->target()->kit();
|
2012-06-24 20:30:02 +03:00
|
|
|
env = bc->environment();
|
2015-12-03 11:13:42 +01:00
|
|
|
if (QMakeStep *qs = bc->qmakeStep())
|
|
|
|
qmakeArgs = qs->parserArguments();
|
2012-08-15 18:17:26 +02:00
|
|
|
else
|
2011-10-28 10:15:04 +00:00
|
|
|
qmakeArgs = bc->configCommandLineArguments();
|
|
|
|
} else {
|
2013-08-21 12:48:46 +02:00
|
|
|
k = KitManager::defaultKit();
|
2009-12-07 20:49:39 +01:00
|
|
|
}
|
2009-12-07 22:58:47 +01:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(k);
|
2016-10-21 20:23:07 +02:00
|
|
|
m_qmakeSysroot = SysRootKitInformation::hasSysRoot(k)
|
2012-09-03 18:31:44 +02:00
|
|
|
? SysRootKitInformation::sysRoot(k).toString() : QString();
|
2012-04-24 15:49:09 +02:00
|
|
|
|
2012-06-18 18:16:50 +02:00
|
|
|
if (qtVersion && qtVersion->isValid()) {
|
|
|
|
m_qmakeGlobals->qmake_abslocation = QDir::cleanPath(qtVersion->qmakeCommand().toString());
|
2012-06-18 17:42:20 +02:00
|
|
|
m_qmakeGlobals->setProperties(qtVersion->versionInfo());
|
2012-06-18 18:16:50 +02:00
|
|
|
}
|
2016-01-08 12:49:00 +01:00
|
|
|
m_qmakeGlobals->setDirectories(rootProjectNode()->sourceDir(), rootProjectNode()->buildDir());
|
2011-10-28 10:15:04 +00:00
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
Environment::const_iterator eit = env.constBegin(), eend = env.constEnd();
|
2011-10-28 10:15:04 +00:00
|
|
|
for (; eit != eend; ++eit)
|
2012-05-02 15:20:08 +02:00
|
|
|
m_qmakeGlobals->environment.insert(env.key(eit), env.value(eit));
|
2011-10-28 10:15:04 +00:00
|
|
|
|
2016-01-08 12:49:00 +01:00
|
|
|
m_qmakeGlobals->setCommandLineArguments(rootProjectNode()->buildDir(), qmakeArgs);
|
2011-10-28 10:15:04 +00:00
|
|
|
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->incRefCount();
|
2014-04-02 03:16:09 +02:00
|
|
|
|
|
|
|
// On ios, qmake is called recursively, and the second call with a different
|
|
|
|
// spec.
|
|
|
|
// macx-ios-clang just creates supporting makefiles, and to avoid being
|
|
|
|
// slow does not evaluate everything, and contains misleading information
|
|
|
|
// (that is never used).
|
|
|
|
// macx-xcode correctly evaluates the variables and generates the xcodeproject
|
|
|
|
// that is actually used to build the application.
|
|
|
|
//
|
|
|
|
// It is important to override the spec file only for the creator evaluator,
|
|
|
|
// and not the qmake buildstep used to build the app (as we use the makefiles).
|
|
|
|
const char IOSQT[] = "Qt4ProjectManager.QtVersion.Ios"; // from Ios::Constants
|
2014-04-03 10:16:48 +02:00
|
|
|
if (qtVersion && qtVersion->type() == QLatin1String(IOSQT))
|
2014-04-02 03:16:09 +02:00
|
|
|
m_qmakeGlobals->xqmakespec = QLatin1String("macx-xcode");
|
2009-12-07 20:49:39 +01:00
|
|
|
}
|
2012-05-02 15:20:08 +02:00
|
|
|
++m_qmakeGlobalsRefCnt;
|
2009-12-07 20:49:39 +01:00
|
|
|
|
2016-04-04 11:26:30 +02:00
|
|
|
auto reader = new QtSupport::ProFileReader(m_qmakeGlobals, m_qmakeVfs);
|
2009-12-07 20:49:39 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
reader->setOutputDir(qmakeProFileNode->buildDir());
|
2009-12-07 20:49:39 +01:00
|
|
|
|
|
|
|
return reader;
|
|
|
|
}
|
|
|
|
|
2016-10-21 20:23:07 +02:00
|
|
|
QMakeGlobals *QmakeProject::qmakeGlobals()
|
2011-10-07 15:40:38 +02:00
|
|
|
{
|
2012-05-02 15:20:08 +02:00
|
|
|
return m_qmakeGlobals;
|
2011-10-07 15:40:38 +02:00
|
|
|
}
|
|
|
|
|
2014-09-10 12:53:55 +02:00
|
|
|
QMakeVfs *QmakeProject::qmakeVfs()
|
|
|
|
{
|
|
|
|
return m_qmakeVfs;
|
|
|
|
}
|
|
|
|
|
2016-10-21 20:23:07 +02:00
|
|
|
QString QmakeProject::qmakeSysroot()
|
|
|
|
{
|
|
|
|
return m_qmakeSysroot;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::destroyProFileReader(QtSupport::ProFileReader *reader)
|
2009-12-07 20:49:39 +01:00
|
|
|
{
|
|
|
|
delete reader;
|
2012-05-02 15:20:08 +02:00
|
|
|
if (!--m_qmakeGlobalsRefCnt) {
|
2016-01-08 11:09:37 +01:00
|
|
|
QString dir = projectFilePath().toString();
|
2009-12-07 22:58:47 +01:00
|
|
|
if (!dir.endsWith(QLatin1Char('/')))
|
|
|
|
dir += QLatin1Char('/');
|
2011-05-20 21:40:53 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFiles(dir);
|
|
|
|
QtSupport::ProFileCacheManager::instance()->decRefCount();
|
2009-12-07 22:58:47 +01:00
|
|
|
|
2012-05-02 15:20:08 +02:00
|
|
|
delete m_qmakeGlobals;
|
2016-04-04 11:26:30 +02:00
|
|
|
m_qmakeGlobals = nullptr;
|
2009-12-07 20:49:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-08 12:49:00 +01:00
|
|
|
QmakeProFileNode *QmakeProject::rootProjectNode() const
|
2011-08-18 16:46:44 +02:00
|
|
|
{
|
2016-01-08 12:49:00 +01:00
|
|
|
return static_cast<QmakeProFileNode *>(Project::rootProjectNode());
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
bool QmakeProject::validParse(const FileName &proFilePath) const
|
2010-10-27 16:27:22 +02:00
|
|
|
{
|
2016-01-08 12:49:00 +01:00
|
|
|
if (!rootProjectNode())
|
2010-10-29 12:15:30 +02:00
|
|
|
return false;
|
2016-01-08 12:49:00 +01:00
|
|
|
const QmakeProFileNode *node = rootProjectNode()->findProFileFor(proFilePath);
|
2010-10-27 16:27:22 +02:00
|
|
|
return node && node->validParse();
|
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
bool QmakeProject::parseInProgress(const FileName &proFilePath) const
|
2011-06-10 15:37:10 +02:00
|
|
|
{
|
2016-01-08 12:49:00 +01:00
|
|
|
if (!rootProjectNode())
|
2011-06-10 15:37:10 +02:00
|
|
|
return false;
|
2016-01-08 12:49:00 +01:00
|
|
|
const QmakeProFileNode *node = rootProjectNode()->findProFileFor(proFilePath);
|
2011-06-10 15:37:10 +02:00
|
|
|
return node && node->parseInProgress();
|
|
|
|
}
|
|
|
|
|
2014-06-04 12:50:10 +02:00
|
|
|
void QmakeProject::collectAllProFiles(QList<QmakeProFileNode *> &list, QmakeProFileNode *node, Parsing parse,
|
|
|
|
const QList<QmakeProjectType> &projectTypes)
|
2010-07-23 16:37:10 +02:00
|
|
|
{
|
2013-06-18 19:12:48 +02:00
|
|
|
if (parse == ExactAndCumulativeParse || node->includedInExactParse())
|
2014-06-04 12:50:10 +02:00
|
|
|
if (projectTypes.isEmpty() || projectTypes.contains(node->projectType()))
|
2013-06-18 19:12:48 +02:00
|
|
|
list.append(node);
|
2008-12-02 12:01:29 +01:00
|
|
|
foreach (ProjectNode *n, node->subProjectNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
QmakeProFileNode *qmakeProFileNode = dynamic_cast<QmakeProFileNode *>(n);
|
2013-10-29 17:37:39 +01:00
|
|
|
if (qmakeProFileNode)
|
2014-06-04 12:50:10 +02:00
|
|
|
collectAllProFiles(list, qmakeProFileNode, parse, projectTypes);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-04 12:50:10 +02:00
|
|
|
QList<QmakeProFileNode *> QmakeProject::applicationProFiles(Parsing parse) const
|
2010-07-23 16:37:10 +02:00
|
|
|
{
|
2014-06-04 12:50:10 +02:00
|
|
|
return allProFiles(QList<QmakeProjectType>() << ApplicationTemplate << ScriptTemplate, parse);
|
2010-07-23 16:37:10 +02:00
|
|
|
}
|
|
|
|
|
2014-06-04 12:50:10 +02:00
|
|
|
QList<QmakeProFileNode *> QmakeProject::allProFiles(const QList<QmakeProjectType> &projectTypes, Parsing parse) const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakeProFileNode *> list;
|
2010-02-08 15:50:06 +01:00
|
|
|
if (!rootProjectNode())
|
|
|
|
return list;
|
2016-01-08 12:49:00 +01:00
|
|
|
collectAllProFiles(list, rootProjectNode(), parse, projectTypes);
|
2008-12-02 12:01:29 +01:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
bool QmakeProject::hasApplicationProFile(const FileName &path) const
|
2010-01-19 13:41:02 +01:00
|
|
|
{
|
|
|
|
if (path.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakeProFileNode *> list = applicationProFiles();
|
|
|
|
foreach (QmakeProFileNode * node, list)
|
2015-10-29 17:53:47 +01:00
|
|
|
if (node->filePath() == path)
|
2010-01-19 13:41:02 +01:00
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-12 16:24:52 +02:00
|
|
|
QList<QmakeProFileNode *> QmakeProject::nodesWithQtcRunnable(QList<QmakeProFileNode *> nodes)
|
|
|
|
{
|
|
|
|
std::function<bool (QmakeProFileNode *)> hasQtcRunnable = [](QmakeProFileNode *node) {
|
|
|
|
return node->isQtcRunnable();
|
|
|
|
};
|
|
|
|
|
|
|
|
if (anyOf(nodes, hasQtcRunnable))
|
|
|
|
erase(nodes, std::not1(hasQtcRunnable));
|
|
|
|
return nodes;
|
|
|
|
}
|
|
|
|
|
2014-07-01 11:08:26 +02:00
|
|
|
QList<Core::Id> QmakeProject::idsForNodes(Core::Id base, const QList<QmakeProFileNode *> &nodes)
|
2010-01-19 13:41:02 +01:00
|
|
|
{
|
2014-06-04 13:11:25 +02:00
|
|
|
return Utils::transform(nodes, [&base](QmakeProFileNode *node) {
|
2015-10-29 17:53:47 +01:00
|
|
|
return base.withSuffix(node->filePath().toString());
|
2014-06-04 13:11:25 +02:00
|
|
|
});
|
2010-01-19 13:41:02 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::activeTargetWasChanged()
|
2010-02-08 15:50:06 +01:00
|
|
|
{
|
2012-08-27 15:11:28 +02:00
|
|
|
if (m_activeTarget) {
|
2015-02-01 18:44:47 +02:00
|
|
|
disconnect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
|
|
|
this, &QmakeProject::scheduleAsyncUpdateLater);
|
2012-08-27 15:11:28 +02:00
|
|
|
}
|
2012-07-17 15:56:43 +02:00
|
|
|
|
|
|
|
m_activeTarget = activeTarget();
|
|
|
|
|
|
|
|
if (!m_activeTarget)
|
2010-02-08 15:50:06 +01:00
|
|
|
return;
|
|
|
|
|
2015-02-01 18:44:47 +02:00
|
|
|
connect(m_activeTarget, &Target::activeBuildConfigurationChanged,
|
|
|
|
this, &QmakeProject::scheduleAsyncUpdateLater);
|
2012-07-17 15:56:43 +02:00
|
|
|
|
2010-03-10 16:55:37 +01:00
|
|
|
scheduleAsyncUpdate();
|
2010-02-08 15:50:06 +01:00
|
|
|
}
|
|
|
|
|
2016-11-02 12:10:18 +01:00
|
|
|
void QmakeProject::setAllBuildConfigurationsEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
foreach (Target *t, targets()) {
|
|
|
|
foreach (BuildConfiguration *bc, t->buildConfigurations()) {
|
|
|
|
auto qmakeBc = qobject_cast<QmakeBuildConfiguration *>(bc);
|
|
|
|
if (qmakeBc)
|
|
|
|
qmakeBc->setEnabled(enabled);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
bool QmakeProject::hasSubNode(QmakePriFileNode *root, const FileName &path)
|
2008-12-02 18:14:06 +01:00
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
if (root->filePath() == path)
|
2008-12-05 14:29:18 +01:00
|
|
|
return true;
|
|
|
|
foreach (FolderNode *fn, root->subFolderNodes()) {
|
2015-01-09 15:50:06 +01:00
|
|
|
if (dynamic_cast<QmakeProFileNode *>(fn)) {
|
2008-12-05 14:29:18 +01:00
|
|
|
// we aren't interested in pro file nodes
|
2015-01-09 15:50:06 +01:00
|
|
|
} else if (QmakePriFileNode *qt4prifilenode = dynamic_cast<QmakePriFileNode *>(fn)) {
|
2008-12-05 14:29:18 +01:00
|
|
|
if (hasSubNode(qt4prifilenode, path))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2008-12-02 18:14:06 +01:00
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
void QmakeProject::findProFile(const FileName &fileName, QmakeProFileNode *root, QList<QmakeProFileNode *> &list)
|
2008-12-02 18:14:06 +01:00
|
|
|
{
|
2008-12-05 14:29:18 +01:00
|
|
|
if (hasSubNode(root, fileName))
|
2008-12-02 18:14:06 +01:00
|
|
|
list.append(root);
|
|
|
|
|
|
|
|
foreach (FolderNode *fn, root->subFolderNodes())
|
2015-01-09 15:50:06 +01:00
|
|
|
if (QmakeProFileNode *qt4proFileNode = dynamic_cast<QmakeProFileNode *>(fn))
|
2008-12-02 18:14:06 +01:00
|
|
|
findProFile(fileName, qt4proFileNode, list);
|
|
|
|
}
|
|
|
|
|
2015-02-02 00:37:38 +02:00
|
|
|
void QmakeProject::notifyChanged(const FileName &name)
|
2008-12-02 18:14:06 +01:00
|
|
|
{
|
2016-01-08 16:56:35 +01:00
|
|
|
if (files(QmakeProject::SourceFiles).contains(name.toString())) {
|
2013-10-29 14:22:31 +01:00
|
|
|
QList<QmakeProFileNode *> list;
|
2016-01-08 12:49:00 +01:00
|
|
|
findProFile(name, rootProjectNode(), list);
|
2013-10-29 14:22:31 +01:00
|
|
|
foreach (QmakeProFileNode *node, list) {
|
2015-02-02 00:37:38 +02:00
|
|
|
QtSupport::ProFileCacheManager::instance()->discardFile(name.toString());
|
2014-10-24 12:43:14 +02:00
|
|
|
node->scheduleUpdate(QmakeProFileNode::ParseNow);
|
2009-12-07 22:58:47 +01:00
|
|
|
}
|
2008-12-05 14:29:18 +01:00
|
|
|
}
|
2008-12-02 18:14:06 +01:00
|
|
|
}
|
2009-03-19 15:04:43 +01:00
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::watchFolders(const QStringList &l, QmakePriFileNode *node)
|
2011-08-18 16:46:44 +02:00
|
|
|
{
|
|
|
|
if (l.isEmpty())
|
|
|
|
return;
|
|
|
|
if (!m_centralizedFolderWatcher)
|
|
|
|
m_centralizedFolderWatcher = new Internal::CentralizedFolderWatcher(this);
|
|
|
|
m_centralizedFolderWatcher->watchFolders(l, node);
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::unwatchFolders(const QStringList &l, QmakePriFileNode *node)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2011-08-18 16:46:44 +02:00
|
|
|
if (m_centralizedFolderWatcher && !l.isEmpty())
|
|
|
|
m_centralizedFolderWatcher->unwatchFolders(l, node);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////
|
|
|
|
/// Centralized Folder Watcher
|
|
|
|
////////////
|
|
|
|
|
|
|
|
// All the folder have a trailing slash!
|
|
|
|
|
|
|
|
namespace {
|
2013-05-05 22:43:52 +03:00
|
|
|
bool debugCFW = false;
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
CentralizedFolderWatcher::CentralizedFolderWatcher(QmakeProject *parent)
|
2013-07-01 11:35:38 +02:00
|
|
|
: QObject(parent), m_project(parent)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
2010-10-13 15:33:51 +02:00
|
|
|
m_compressTimer.setSingleShot(true);
|
|
|
|
m_compressTimer.setInterval(200);
|
2016-01-07 18:01:04 +01:00
|
|
|
connect(&m_compressTimer, &QTimer::timeout, this, &CentralizedFolderWatcher::onTimer);
|
|
|
|
connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
|
|
|
|
this, &CentralizedFolderWatcher::folderChanged);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QSet<QString> CentralizedFolderWatcher::recursiveDirs(const QString &folder)
|
|
|
|
{
|
|
|
|
QSet<QString> result;
|
|
|
|
QDir dir(folder);
|
|
|
|
QStringList list = dir.entryList(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
|
|
|
|
foreach (const QString &f, list) {
|
2012-01-13 14:20:45 +01:00
|
|
|
const QString a = folder + f + QLatin1Char('/');
|
2011-02-25 15:27:13 +01:00
|
|
|
result.insert(a);
|
|
|
|
result += recursiveDirs(a);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-02-26 10:36:29 +02:00
|
|
|
void CentralizedFolderWatcher::watchFolders(const QList<QString> &folders, QmakePriFileNode *node)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
if (debugCFW)
|
2015-10-29 17:53:47 +01:00
|
|
|
qDebug()<<"CFW::watchFolders()"<<folders<<"for node"<<node->filePath();
|
2010-08-10 16:27:35 +02:00
|
|
|
m_watcher.addPaths(folders);
|
|
|
|
|
2012-01-13 14:20:45 +01:00
|
|
|
const QChar slash = QLatin1Char('/');
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &f, folders) {
|
|
|
|
QString folder = f;
|
2012-01-13 14:20:45 +01:00
|
|
|
if (!folder.endsWith(slash))
|
|
|
|
folder.append(slash);
|
2010-08-10 16:27:35 +02:00
|
|
|
m_map.insert(folder, node);
|
|
|
|
|
|
|
|
// Support for recursive watching
|
|
|
|
// we add the recursive directories we find
|
|
|
|
QSet<QString> tmp = recursiveDirs(folder);
|
2010-08-12 13:38:21 +02:00
|
|
|
if (!tmp.isEmpty())
|
|
|
|
m_watcher.addPaths(tmp.toList());
|
2010-08-10 16:27:35 +02:00
|
|
|
m_recursiveWatchedFolders += tmp;
|
|
|
|
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"adding recursive dirs for"<< folder<<":"<<tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-26 10:36:29 +02:00
|
|
|
void CentralizedFolderWatcher::unwatchFolders(const QList<QString> &folders, QmakePriFileNode *node)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
if (debugCFW)
|
2015-10-29 17:53:47 +01:00
|
|
|
qDebug()<<"CFW::unwatchFolders()"<<folders<<"for node"<<node->filePath();
|
2012-01-13 14:20:45 +01:00
|
|
|
const QChar slash = QLatin1Char('/');
|
2010-08-10 16:27:35 +02:00
|
|
|
foreach (const QString &f, folders) {
|
|
|
|
QString folder = f;
|
2012-01-13 14:20:45 +01:00
|
|
|
if (!folder.endsWith(slash))
|
|
|
|
folder.append(slash);
|
2010-08-10 16:27:35 +02:00
|
|
|
m_map.remove(folder, node);
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (!m_map.contains(folder))
|
2010-08-10 16:27:35 +02:00
|
|
|
m_watcher.removePath(folder);
|
|
|
|
|
|
|
|
// Figure out which recursive directories we can remove
|
2012-05-03 16:15:38 +02:00
|
|
|
// this might not scale. I'm pretty sure it doesn't
|
2010-08-10 16:27:35 +02:00
|
|
|
// A scaling implementation would need to save more information
|
|
|
|
// where a given directory watcher actual comes from...
|
|
|
|
|
|
|
|
QStringList toRemove;
|
|
|
|
foreach (const QString &rwf, m_recursiveWatchedFolders) {
|
|
|
|
if (rwf.startsWith(folder)) {
|
|
|
|
// So the rwf is a subdirectory of a folder we aren't watching
|
|
|
|
// but maybe someone else wants us to watch
|
|
|
|
bool needToWatch = false;
|
2014-02-26 10:36:29 +02:00
|
|
|
QMultiMap<QString, QmakePriFileNode *>::const_iterator it, end;
|
2010-08-10 16:27:35 +02:00
|
|
|
end = m_map.constEnd();
|
|
|
|
for (it = m_map.constEnd(); it != end; ++it) {
|
|
|
|
if (rwf.startsWith(it.key())) {
|
|
|
|
needToWatch = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!needToWatch) {
|
|
|
|
m_watcher.removePath(rwf);
|
|
|
|
toRemove << rwf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"removing recursive dirs for"<<folder<<":"<<toRemove;
|
|
|
|
|
|
|
|
foreach (const QString &tr, toRemove) {
|
|
|
|
m_recursiveWatchedFolders.remove(tr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::folderChanged(const QString &folder)
|
2010-10-13 15:33:51 +02:00
|
|
|
{
|
|
|
|
m_changedFolders.insert(folder);
|
|
|
|
m_compressTimer.start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::onTimer()
|
|
|
|
{
|
2012-11-28 20:44:03 +02:00
|
|
|
foreach (const QString &folder, m_changedFolders)
|
2010-10-13 15:33:51 +02:00
|
|
|
delayedFolderChanged(folder);
|
|
|
|
m_changedFolders.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CentralizedFolderWatcher::delayedFolderChanged(const QString &folder)
|
2010-08-10 16:27:35 +02:00
|
|
|
{
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"CFW::folderChanged"<<folder;
|
|
|
|
// Figure out whom to inform
|
|
|
|
|
2010-08-18 12:53:37 +02:00
|
|
|
QString dir = folder;
|
2012-01-13 14:20:45 +01:00
|
|
|
const QChar slash = QLatin1Char('/');
|
2013-07-01 11:35:38 +02:00
|
|
|
bool newOrRemovedFiles = false;
|
2010-08-10 16:27:35 +02:00
|
|
|
while (true) {
|
2012-01-13 14:20:45 +01:00
|
|
|
if (!dir.endsWith(slash))
|
|
|
|
dir.append(slash);
|
2014-02-26 10:36:29 +02:00
|
|
|
QList<QmakePriFileNode *> nodes = m_map.values(dir);
|
2013-07-01 11:35:38 +02:00
|
|
|
if (!nodes.isEmpty()) {
|
|
|
|
// Collect all the files
|
2015-02-01 18:44:47 +02:00
|
|
|
QSet<FileName> newFiles;
|
2013-10-29 14:22:31 +01:00
|
|
|
newFiles += QmakePriFileNode::recursiveEnumerate(folder);
|
2014-02-26 10:36:29 +02:00
|
|
|
foreach (QmakePriFileNode *node, nodes) {
|
2013-07-01 11:35:38 +02:00
|
|
|
newOrRemovedFiles = newOrRemovedFiles
|
|
|
|
|| node->folderChanged(folder, newFiles);
|
|
|
|
}
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
2010-08-18 12:53:37 +02:00
|
|
|
// Chop off last part, and break if there's nothing to chop off
|
|
|
|
//
|
|
|
|
if (dir.length() < 2)
|
2010-08-10 16:27:35 +02:00
|
|
|
break;
|
2010-08-18 12:53:37 +02:00
|
|
|
|
|
|
|
// We start before the last slash
|
2012-01-13 14:20:45 +01:00
|
|
|
const int index = dir.lastIndexOf(slash, dir.length() - 2);
|
2010-08-18 12:53:37 +02:00
|
|
|
if (index == -1)
|
|
|
|
break;
|
2012-01-13 14:20:45 +01:00
|
|
|
dir.truncate(index + 1);
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
2010-08-16 13:01:36 +02:00
|
|
|
QString folderWithSlash = folder;
|
2012-01-13 14:20:45 +01:00
|
|
|
if (!folder.endsWith(slash))
|
|
|
|
folderWithSlash.append(slash);
|
2010-08-16 13:01:36 +02:00
|
|
|
|
2010-08-10 16:27:35 +02:00
|
|
|
// If a subdirectory was added, watch it too
|
2010-08-16 13:01:36 +02:00
|
|
|
QSet<QString> tmp = recursiveDirs(folderWithSlash);
|
2010-08-10 16:27:35 +02:00
|
|
|
if (!tmp.isEmpty()) {
|
|
|
|
if (debugCFW)
|
|
|
|
qDebug()<<"found new recursive dirs"<<tmp;
|
2010-10-13 14:44:32 +02:00
|
|
|
|
|
|
|
QSet<QString> alreadyAdded = m_watcher.directories().toSet();
|
|
|
|
tmp.subtract(alreadyAdded);
|
|
|
|
if (!tmp.isEmpty())
|
|
|
|
m_watcher.addPaths(tmp.toList());
|
2010-08-10 16:27:35 +02:00
|
|
|
m_recursiveWatchedFolders += tmp;
|
|
|
|
}
|
2013-07-01 11:35:38 +02:00
|
|
|
|
|
|
|
if (newOrRemovedFiles) {
|
|
|
|
m_project->updateFileList();
|
|
|
|
m_project->updateCodeModels();
|
|
|
|
}
|
2010-08-10 16:27:35 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
bool QmakeProject::needsConfiguration() const
|
2011-10-28 10:15:04 +00:00
|
|
|
{
|
|
|
|
return targets().isEmpty();
|
|
|
|
}
|
|
|
|
|
2015-11-27 16:14:14 +01:00
|
|
|
void QmakeProject::configureAsExampleProject(const QSet<Core::Id> &platforms)
|
2012-03-06 13:14:42 +01:00
|
|
|
{
|
2013-08-13 10:52:57 +02:00
|
|
|
QList<const BuildInfo *> infoList;
|
2014-09-12 01:08:28 +02:00
|
|
|
QList<Kit *> kits = KitManager::kits();
|
2012-09-03 18:31:44 +02:00
|
|
|
foreach (Kit *k, kits) {
|
|
|
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(k);
|
2015-12-09 13:57:35 +01:00
|
|
|
if (!version
|
|
|
|
|| (!platforms.isEmpty()
|
|
|
|
&& !Utils::contains(version->targetDeviceTypes(), [platforms](Core::Id i) { return platforms.contains(i); })))
|
2012-04-24 15:49:09 +02:00
|
|
|
continue;
|
|
|
|
|
2014-05-02 12:22:58 +02:00
|
|
|
IBuildConfigurationFactory *factory = IBuildConfigurationFactory::find(k, projectFilePath().toString());
|
2013-08-13 10:52:57 +02:00
|
|
|
if (!factory)
|
2012-04-24 15:49:09 +02:00
|
|
|
continue;
|
2014-05-02 12:22:58 +02:00
|
|
|
foreach (BuildInfo *info, factory->availableSetups(k, projectFilePath().toString()))
|
2013-08-13 10:52:57 +02:00
|
|
|
infoList << info;
|
2012-03-06 13:14:42 +01:00
|
|
|
}
|
2013-08-13 10:52:57 +02:00
|
|
|
setup(infoList);
|
|
|
|
qDeleteAll(infoList);
|
2012-03-06 13:14:42 +01:00
|
|
|
}
|
|
|
|
|
2014-07-11 12:04:30 +02:00
|
|
|
bool QmakeProject::requiresTargetPanel() const
|
2012-09-06 16:19:14 +02:00
|
|
|
{
|
2015-09-16 16:33:33 +02:00
|
|
|
return !targets().isEmpty();
|
2012-09-06 16:19:14 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 18:24:57 +01:00
|
|
|
// All the Qmake run configurations should share code.
|
2012-05-09 12:44:37 +02:00
|
|
|
// This is a rather suboptimal way to do that for disabledReason()
|
|
|
|
// but more pratical then duplicated the code everywhere
|
2015-02-02 00:37:38 +02:00
|
|
|
QString QmakeProject::disabledReasonForRunConfiguration(const FileName &proFilePath)
|
2012-05-09 12:44:37 +02:00
|
|
|
{
|
2015-02-02 00:37:38 +02:00
|
|
|
if (!proFilePath.exists())
|
2014-04-17 14:09:47 +02:00
|
|
|
return tr("The .pro file \"%1\" does not exist.")
|
2015-02-02 00:37:38 +02:00
|
|
|
.arg(proFilePath.fileName());
|
2012-05-09 12:44:37 +02:00
|
|
|
|
2016-01-08 12:49:00 +01:00
|
|
|
if (!rootProjectNode()) // Shutting down
|
2012-06-28 13:10:33 +02:00
|
|
|
return QString();
|
|
|
|
|
2016-01-08 12:49:00 +01:00
|
|
|
if (!rootProjectNode()->findProFileFor(proFilePath))
|
2014-04-17 14:09:47 +02:00
|
|
|
return tr("The .pro file \"%1\" is not part of the project.")
|
2015-02-02 00:37:38 +02:00
|
|
|
.arg(proFilePath.fileName());
|
2012-05-09 12:44:37 +02:00
|
|
|
|
2014-04-17 14:09:47 +02:00
|
|
|
return tr("The .pro file \"%1\" could not be parsed.")
|
2015-02-02 00:37:38 +02:00
|
|
|
.arg(proFilePath.fileName());
|
2012-05-09 12:44:37 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProject::buildNameFor(const Kit *k)
|
2012-04-24 15:49:09 +02:00
|
|
|
{
|
2012-09-09 20:41:30 +03:00
|
|
|
if (!k)
|
2012-04-24 15:49:09 +02:00
|
|
|
return QLatin1String("unknown");
|
2012-10-04 14:40:29 +02:00
|
|
|
|
|
|
|
return k->fileSystemFriendlyName();
|
2012-04-24 15:49:09 +02:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::updateBuildSystemData()
|
2012-08-20 12:41:52 +02:00
|
|
|
{
|
|
|
|
Target * const target = activeTarget();
|
|
|
|
if (!target)
|
|
|
|
return;
|
2016-01-08 12:49:00 +01:00
|
|
|
const QmakeProFileNode * const rootNode = rootProjectNode();
|
2012-08-20 12:41:52 +02:00
|
|
|
if (!rootNode || rootNode->parseInProgress())
|
|
|
|
return;
|
|
|
|
|
|
|
|
DeploymentData deploymentData;
|
|
|
|
collectData(rootNode, deploymentData);
|
|
|
|
target->setDeploymentData(deploymentData);
|
|
|
|
|
|
|
|
BuildTargetInfoList appTargetList;
|
2014-08-07 15:53:54 +02:00
|
|
|
foreach (const QmakeProFileNode * const node, applicationProFiles()) {
|
|
|
|
appTargetList.list << BuildTargetInfo(node->targetInformation().target,
|
2015-02-01 18:44:47 +02:00
|
|
|
FileName::fromString(executableFor(node)),
|
2015-10-29 17:53:47 +01:00
|
|
|
node->filePath());
|
2014-08-07 15:53:54 +02:00
|
|
|
}
|
2012-08-20 12:41:52 +02:00
|
|
|
target->setApplicationTargets(appTargetList);
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::collectData(const QmakeProFileNode *node, DeploymentData &deploymentData)
|
2012-08-20 12:41:52 +02:00
|
|
|
{
|
2015-10-29 17:53:47 +01:00
|
|
|
if (!node->isSubProjectDeployable(node->filePath().toString()))
|
2012-08-20 12:41:52 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
const InstallsList &installsList = node->installsList();
|
|
|
|
foreach (const InstallsItem &item, installsList.items) {
|
2016-10-25 21:25:25 +02:00
|
|
|
if (!item.active)
|
|
|
|
continue;
|
|
|
|
foreach (const auto &localFile, item.files)
|
|
|
|
deploymentData.addFile(localFile.fileName, item.path);
|
2012-08-20 12:41:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (node->projectType()) {
|
|
|
|
case ApplicationTemplate:
|
|
|
|
if (!installsList.targetPath.isEmpty())
|
2013-03-12 14:09:18 +01:00
|
|
|
collectApplicationData(node, deploymentData);
|
2012-08-20 12:41:52 +02:00
|
|
|
break;
|
2015-03-17 11:39:48 +02:00
|
|
|
case SharedLibraryTemplate:
|
|
|
|
case StaticLibraryTemplate:
|
2012-08-20 12:41:52 +02:00
|
|
|
collectLibraryData(node, deploymentData);
|
|
|
|
break;
|
|
|
|
case SubDirsTemplate:
|
|
|
|
foreach (const ProjectNode * const subProject, node->subProjectNodesExact()) {
|
2013-10-29 14:22:31 +01:00
|
|
|
const QmakeProFileNode * const qt4SubProject
|
2015-01-09 15:50:06 +01:00
|
|
|
= dynamic_cast<const QmakeProFileNode *>(subProject);
|
2012-08-20 12:41:52 +02:00
|
|
|
if (!qt4SubProject)
|
|
|
|
continue;
|
|
|
|
collectData(qt4SubProject, deploymentData);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::collectApplicationData(const QmakeProFileNode *node, DeploymentData &deploymentData)
|
2013-03-12 14:09:18 +01:00
|
|
|
{
|
|
|
|
QString executable = executableFor(node);
|
|
|
|
if (!executable.isEmpty())
|
|
|
|
deploymentData.addFile(executable, node->installsList().targetPath,
|
|
|
|
DeployableFile::TypeExecutable);
|
|
|
|
}
|
|
|
|
|
2014-04-08 17:28:39 +02:00
|
|
|
static QString destDirFor(const TargetInformation &ti)
|
|
|
|
{
|
|
|
|
if (ti.destDir.isEmpty())
|
|
|
|
return ti.buildDir;
|
|
|
|
if (QDir::isRelativePath(ti.destDir))
|
|
|
|
return QDir::cleanPath(ti.buildDir + QLatin1Char('/') + ti.destDir);
|
|
|
|
return ti.destDir;
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::collectLibraryData(const QmakeProFileNode *node, DeploymentData &deploymentData)
|
2012-08-20 12:41:52 +02:00
|
|
|
{
|
|
|
|
const QString targetPath = node->installsList().targetPath;
|
|
|
|
if (targetPath.isEmpty())
|
|
|
|
return;
|
2015-02-01 18:44:47 +02:00
|
|
|
const Kit * const kit = activeTarget()->kit();
|
2016-07-12 16:27:45 +02:00
|
|
|
const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ToolChain::Language::Cxx);
|
2012-08-20 12:41:52 +02:00
|
|
|
if (!toolchain)
|
|
|
|
return;
|
|
|
|
|
|
|
|
TargetInformation ti = node->targetInformation();
|
|
|
|
QString targetFileName = ti.target;
|
|
|
|
const QStringList config = node->variableValue(ConfigVar);
|
|
|
|
const bool isStatic = config.contains(QLatin1String("static"));
|
|
|
|
const bool isPlugin = config.contains(QLatin1String("plugin"));
|
|
|
|
switch (toolchain->targetAbi().os()) {
|
2015-02-01 18:44:47 +02:00
|
|
|
case Abi::WindowsOS: {
|
2012-08-20 12:41:52 +02:00
|
|
|
QString targetVersionExt = node->singleVariableValue(TargetVersionExtVar);
|
|
|
|
if (targetVersionExt.isEmpty()) {
|
|
|
|
const QString version = node->singleVariableValue(VersionVar);
|
|
|
|
if (!version.isEmpty()) {
|
|
|
|
targetVersionExt = version.left(version.indexOf(QLatin1Char('.')));
|
|
|
|
if (targetVersionExt == QLatin1String("0"))
|
|
|
|
targetVersionExt.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
targetFileName += targetVersionExt + QLatin1Char('.');
|
|
|
|
targetFileName += QLatin1String(isStatic ? "lib" : "dll");
|
2013-03-12 14:09:18 +01:00
|
|
|
deploymentData.addFile(destDirFor(ti) + QLatin1Char('/') + targetFileName, targetPath);
|
2012-08-20 12:41:52 +02:00
|
|
|
break;
|
|
|
|
}
|
2016-07-25 18:39:16 -07:00
|
|
|
case Abi::DarwinOS: {
|
2013-03-12 14:09:18 +01:00
|
|
|
QString destDir = destDirFor(ti);
|
2012-11-26 15:09:56 +02:00
|
|
|
if (config.contains(QLatin1String("lib_bundle"))) {
|
2013-03-12 14:09:18 +01:00
|
|
|
destDir.append(QLatin1Char('/')).append(ti.target)
|
2012-08-20 12:41:52 +02:00
|
|
|
.append(QLatin1String(".framework"));
|
|
|
|
} else {
|
2016-10-05 13:25:35 +03:00
|
|
|
if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix"))))
|
|
|
|
targetFileName.prepend(QLatin1String("lib"));
|
|
|
|
|
2012-08-20 12:41:52 +02:00
|
|
|
if (!isPlugin) {
|
|
|
|
targetFileName += QLatin1Char('.');
|
|
|
|
const QString version = node->singleVariableValue(VersionVar);
|
|
|
|
QString majorVersion = version.left(version.indexOf(QLatin1Char('.')));
|
|
|
|
if (majorVersion.isEmpty())
|
|
|
|
majorVersion = QLatin1String("1");
|
|
|
|
targetFileName += majorVersion;
|
|
|
|
}
|
|
|
|
targetFileName += QLatin1Char('.');
|
|
|
|
targetFileName += node->singleVariableValue(isStatic
|
|
|
|
? StaticLibExtensionVar : ShLibExtensionVar);
|
|
|
|
}
|
2013-03-12 14:09:18 +01:00
|
|
|
deploymentData.addFile(destDir + QLatin1Char('/') + targetFileName, targetPath);
|
2012-08-20 12:41:52 +02:00
|
|
|
break;
|
2013-03-12 14:09:18 +01:00
|
|
|
}
|
2015-02-01 18:44:47 +02:00
|
|
|
case Abi::LinuxOS:
|
|
|
|
case Abi::BsdOS:
|
|
|
|
case Abi::UnixOS:
|
2016-10-05 13:25:35 +03:00
|
|
|
if (!(isPlugin && config.contains(QLatin1String("no_plugin_name_prefix"))))
|
|
|
|
targetFileName.prepend(QLatin1String("lib"));
|
|
|
|
|
2012-08-20 12:41:52 +02:00
|
|
|
targetFileName += QLatin1Char('.');
|
|
|
|
if (isStatic) {
|
|
|
|
targetFileName += QLatin1Char('a');
|
|
|
|
} else {
|
|
|
|
targetFileName += QLatin1String("so");
|
2013-03-12 14:09:18 +01:00
|
|
|
deploymentData.addFile(destDirFor(ti) + QLatin1Char('/') + targetFileName, targetPath);
|
2012-08-20 12:41:52 +02:00
|
|
|
if (!isPlugin) {
|
|
|
|
QString version = node->singleVariableValue(VersionVar);
|
|
|
|
if (version.isEmpty())
|
|
|
|
version = QLatin1String("1.0.0");
|
|
|
|
targetFileName += QLatin1Char('.');
|
|
|
|
while (true) {
|
2013-03-12 14:09:18 +01:00
|
|
|
deploymentData.addFile(destDirFor(ti) + QLatin1Char('/')
|
2012-08-20 12:41:52 +02:00
|
|
|
+ targetFileName + version, targetPath);
|
|
|
|
const QString tmpVersion = version.left(version.lastIndexOf(QLatin1Char('.')));
|
|
|
|
if (tmpVersion == version)
|
|
|
|
break;
|
|
|
|
version = tmpVersion;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-20 17:23:07 +02:00
|
|
|
bool QmakeProject::matchesKit(const Kit *kit)
|
|
|
|
{
|
|
|
|
QList<QtSupport::BaseQtVersion *> parentQts;
|
2015-02-01 18:44:47 +02:00
|
|
|
FileName filePath = projectFilePath();
|
2014-10-20 17:23:07 +02:00
|
|
|
foreach (QtSupport::BaseQtVersion *version, QtSupport::QtVersionManager::validVersions()) {
|
2014-11-20 18:27:01 +01:00
|
|
|
if (version->isSubProject(filePath))
|
2014-10-20 17:23:07 +02:00
|
|
|
parentQts.append(version);
|
|
|
|
}
|
|
|
|
|
|
|
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
|
|
|
|
if (!parentQts.isEmpty())
|
|
|
|
return parentQts.contains(version);
|
2014-11-11 14:19:50 +01:00
|
|
|
return false;
|
2014-10-20 17:23:07 +02:00
|
|
|
}
|
|
|
|
|
2016-09-23 15:53:31 +02:00
|
|
|
static Utils::FileName getFullPathOf(const QString &exe, const BuildConfiguration *bc)
|
|
|
|
{
|
|
|
|
QTC_ASSERT(bc, return Utils::FileName::fromString(exe));
|
|
|
|
QFileInfo fi(exe);
|
|
|
|
if (fi.isAbsolute())
|
|
|
|
return Utils::FileName::fromString(exe);
|
|
|
|
|
|
|
|
return bc->environment().searchInPath(exe);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmakeProject::testToolChain(ToolChain *tc, const Utils::FileName &path) const
|
|
|
|
{
|
|
|
|
if (!tc || path.isEmpty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const Utils::FileName expected = tc->compilerCommand();
|
|
|
|
if (expected != path) {
|
|
|
|
const QPair<Utils::FileName, Utils::FileName> pair = qMakePair(expected, path);
|
|
|
|
if (!m_toolChainWarnings.contains(pair)) {
|
|
|
|
TaskHub::addTask(Task(Task::Warning,
|
|
|
|
QCoreApplication::translate("QmakeProjectManager", "\"%1\" is used by qmake, but \"%2\" is configured in the kit.\n"
|
|
|
|
"Please update your kit or choose a mkspec for qmake that matches your target environment better.").
|
|
|
|
arg(path.toUserOutput()).arg(expected.toUserOutput()),
|
|
|
|
Utils::FileName(), -1, ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
|
|
|
|
m_toolChainWarnings.insert(pair);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void QmakeProject::warnOnToolChainMismatch(const QmakeProFileNode *pro) const
|
|
|
|
{
|
|
|
|
Target *t = activeTarget();
|
|
|
|
if (!t)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
|
|
|
|
if (!bc)
|
|
|
|
return;
|
|
|
|
|
|
|
|
testToolChain(ToolChainKitInformation::toolChain(t->kit(), ToolChain::Language::C),
|
|
|
|
getFullPathOf(pro->singleVariableValue(QmakeCc), bc));
|
|
|
|
testToolChain(ToolChainKitInformation::toolChain(t->kit(), ToolChain::Language::Cxx),
|
|
|
|
getFullPathOf(pro->singleVariableValue(QmakeCxx), bc));
|
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
QString QmakeProject::executableFor(const QmakeProFileNode *node)
|
2013-03-12 14:09:18 +01:00
|
|
|
{
|
2015-02-01 18:44:47 +02:00
|
|
|
const Kit * const kit = activeTarget()->kit();
|
2016-07-12 16:27:45 +02:00
|
|
|
const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ToolChain::Language::Cxx);
|
2013-03-12 14:09:18 +01:00
|
|
|
if (!toolchain)
|
|
|
|
return QString();
|
|
|
|
|
|
|
|
TargetInformation ti = node->targetInformation();
|
2013-12-23 15:01:10 +02:00
|
|
|
QString target;
|
2013-03-12 14:09:18 +01:00
|
|
|
|
|
|
|
switch (toolchain->targetAbi().os()) {
|
2016-07-25 18:39:16 -07:00
|
|
|
case Abi::DarwinOS:
|
2013-12-23 15:01:10 +02:00
|
|
|
if (node->variableValue(ConfigVar).contains(QLatin1String("app_bundle"))) {
|
|
|
|
target = ti.target + QLatin1String(".app/Contents/MacOS/") + ti.target;
|
|
|
|
break;
|
|
|
|
}
|
2013-03-12 14:09:18 +01:00
|
|
|
// else fall through
|
2014-10-02 14:45:14 +02:00
|
|
|
default: {
|
2013-03-12 14:09:18 +01:00
|
|
|
QString extension = node->singleVariableValue(TargetExtVar);
|
2013-12-23 15:01:10 +02:00
|
|
|
target = ti.target + extension;
|
|
|
|
break;
|
2013-03-12 14:09:18 +01:00
|
|
|
}
|
|
|
|
}
|
2013-12-23 15:01:10 +02:00
|
|
|
return QDir(destDirFor(ti)).absoluteFilePath(target);
|
2013-03-12 14:09:18 +01:00
|
|
|
}
|
|
|
|
|
2013-10-29 14:22:31 +01:00
|
|
|
void QmakeProject::emitBuildDirectoryInitialized()
|
2012-07-13 17:14:42 +02:00
|
|
|
{
|
|
|
|
emit buildDirectoryInitialized();
|
|
|
|
}
|
2013-08-13 10:52:57 +02:00
|
|
|
|
2016-10-05 08:31:16 +02:00
|
|
|
ProjectImporter *QmakeProject::projectImporter() const
|
2013-08-13 10:52:57 +02:00
|
|
|
{
|
2016-10-05 08:31:16 +02:00
|
|
|
if (!m_projectImporter)
|
|
|
|
m_projectImporter = new QmakeProjectImporter(projectFilePath().toString());
|
|
|
|
return m_projectImporter;
|
2013-08-13 10:52:57 +02:00
|
|
|
}
|
|
|
|
|
2014-11-18 17:05:09 +01:00
|
|
|
QmakeProject::AsyncUpdateState QmakeProject::asyncUpdateState() const
|
|
|
|
{
|
|
|
|
return m_asyncUpdateState;
|
|
|
|
}
|
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
} // namespace QmakeProjectManager
|
2011-08-18 16:55:45 +02:00
|
|
|
|
2013-10-16 12:10:22 +02:00
|
|
|
#include "qmakeproject.moc"
|