2013-01-30 18:19:31 +01:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
2014-01-07 13:27:11 +01:00
|
|
|
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
2013-01-30 18:19:31 +01:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
|
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
|
|
|
** General Public License version 2.1 as published by the Free Software
|
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
|
|
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
|
|
|
**
|
|
|
|
|
** In addition, as a special exception, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
|
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "qbsproject.h"
|
|
|
|
|
|
|
|
|
|
#include "qbsbuildconfiguration.h"
|
2013-02-06 11:28:33 +01:00
|
|
|
#include "qbslogsink.h"
|
2013-01-30 18:19:31 +01:00
|
|
|
#include "qbsprojectfile.h"
|
2014-06-16 14:42:21 +02:00
|
|
|
#include "qbsprojectparser.h"
|
2013-01-30 18:19:31 +01:00
|
|
|
#include "qbsprojectmanagerconstants.h"
|
|
|
|
|
#include "qbsnodes.h"
|
|
|
|
|
|
|
|
|
|
#include <coreplugin/documentmanager.h>
|
|
|
|
|
#include <coreplugin/icontext.h>
|
|
|
|
|
#include <coreplugin/id.h>
|
2014-08-18 16:30:43 +02:00
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
#include <coreplugin/iversioncontrol.h>
|
|
|
|
|
#include <coreplugin/vcsmanager.h>
|
2014-07-18 15:46:24 +02:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
|
|
|
|
#include <coreplugin/mimedatabase.h>
|
2013-09-18 13:13:09 +02:00
|
|
|
#include <cpptools/cppmodelmanagerinterface.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <projectexplorer/buildenvironmentwidget.h>
|
2014-02-25 13:50:56 +01:00
|
|
|
#include <projectexplorer/buildmanager.h>
|
2013-09-02 10:12:37 +02:00
|
|
|
#include <projectexplorer/buildtargetinfo.h>
|
|
|
|
|
#include <projectexplorer/deploymentdata.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <projectexplorer/kit.h>
|
|
|
|
|
#include <projectexplorer/kitinformation.h>
|
|
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2014-05-02 11:44:32 +02:00
|
|
|
#include <projectexplorer/projectmacroexpander.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <projectexplorer/target.h>
|
|
|
|
|
#include <projectexplorer/taskhub.h>
|
2013-03-26 15:06:51 +01:00
|
|
|
#include <projectexplorer/toolchain.h>
|
2013-03-27 09:15:01 +01:00
|
|
|
#include <projectexplorer/headerpath.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2013-08-07 12:29:52 +02:00
|
|
|
#include <qtsupport/uicodemodelsupport.h>
|
2012-12-06 17:20:58 +01:00
|
|
|
#include <qmljstools/qmljsmodelmanager.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <qmljs/qmljsmodelmanagerinterface.h>
|
2014-03-28 13:26:46 +01:00
|
|
|
#include <utils/hostosinfo.h>
|
2014-07-18 15:46:24 +02:00
|
|
|
#include <utils/qtcassert.h>
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
#include <qbs.h>
|
|
|
|
|
|
2014-02-25 16:39:09 +01:00
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QDir>
|
2013-01-30 18:19:31 +01:00
|
|
|
#include <QFileInfo>
|
2014-08-18 16:30:43 +02:00
|
|
|
#include <QMessageBox>
|
2014-07-22 09:49:51 +02:00
|
|
|
#include <QVariantMap>
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-08-29 17:56:28 +02:00
|
|
|
using namespace Core;
|
2013-08-29 18:25:59 +02:00
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace Utils;
|
2013-08-29 17:56:28 +02:00
|
|
|
|
|
|
|
|
namespace QbsProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// Constants:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
2013-02-20 17:40:52 +01:00
|
|
|
static const char CONFIG_CPP_MODULE[] = "cpp";
|
2014-01-14 16:48:19 +01:00
|
|
|
static const char CONFIG_CXXFLAGS[] = "cxxFlags";
|
|
|
|
|
static const char CONFIG_CFLAGS[] = "cFlags";
|
2013-02-20 17:40:52 +01:00
|
|
|
static const char CONFIG_DEFINES[] = "defines";
|
|
|
|
|
static const char CONFIG_INCLUDEPATHS[] = "includePaths";
|
2014-07-23 10:48:29 +02:00
|
|
|
static const char CONFIG_SYSTEM_INCLUDEPATHS[] = "systemIncludePaths";
|
2013-02-20 17:40:52 +01:00
|
|
|
static const char CONFIG_FRAMEWORKPATHS[] = "frameworkPaths";
|
2014-07-23 10:48:29 +02:00
|
|
|
static const char CONFIG_SYSTEM_FRAMEWORKPATHS[] = "systemFrameworkPaths";
|
2013-02-20 17:40:52 +01:00
|
|
|
static const char CONFIG_PRECOMPILEDHEADER[] = "precompiledHeader";
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// QbsProject:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
QbsProject::QbsProject(QbsManager *manager, const QString &fileName) :
|
2013-05-16 16:20:06 +02:00
|
|
|
m_manager(manager),
|
|
|
|
|
m_projectName(QFileInfo(fileName).completeBaseName()),
|
|
|
|
|
m_fileName(fileName),
|
2013-05-16 16:24:37 +02:00
|
|
|
m_rootProjectNode(0),
|
2014-06-16 14:42:21 +02:00
|
|
|
m_qbsProjectParser(0),
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsUpdateFutureInterface(0),
|
2014-07-11 12:44:12 +02:00
|
|
|
m_parsingScheduled(false),
|
2014-07-14 14:22:27 +02:00
|
|
|
m_cancelStatus(CancelStatusNone),
|
2013-01-30 18:19:31 +01:00
|
|
|
m_currentBc(0)
|
|
|
|
|
{
|
2013-06-11 18:10:42 +02:00
|
|
|
m_parsingDelay.setInterval(1000); // delay parsing by 1s.
|
2013-06-06 18:45:53 +02:00
|
|
|
|
2013-09-27 16:30:20 +02:00
|
|
|
setId(Constants::PROJECT_ID);
|
2013-08-29 17:56:28 +02:00
|
|
|
setProjectContext(Context(Constants::PROJECT_ID));
|
|
|
|
|
setProjectLanguages(Context(ProjectExplorer::Constants::LANG_CXX));
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
connect(this, SIGNAL(activeTargetChanged(ProjectExplorer::Target*)),
|
|
|
|
|
this, SLOT(changeActiveTarget(ProjectExplorer::Target*)));
|
|
|
|
|
connect(this, SIGNAL(addedTarget(ProjectExplorer::Target*)),
|
|
|
|
|
this, SLOT(targetWasAdded(ProjectExplorer::Target*)));
|
2013-06-06 18:45:53 +02:00
|
|
|
connect(this, SIGNAL(environmentChanged()), this, SLOT(delayParsing()));
|
|
|
|
|
|
2013-11-26 16:19:43 +01:00
|
|
|
connect(&m_parsingDelay, SIGNAL(timeout()), this, SLOT(startParsing()));
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-06-18 15:52:29 +02:00
|
|
|
updateDocuments(QSet<QString>() << fileName);
|
2013-10-21 17:43:10 +02:00
|
|
|
|
|
|
|
|
// NOTE: QbsProjectNode does not use this as a parent!
|
2014-07-10 17:01:54 +02:00
|
|
|
m_rootProjectNode = new QbsRootProjectNode(this); // needs documents to be initialized!
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QbsProject::~QbsProject()
|
|
|
|
|
{
|
|
|
|
|
m_codeModelFuture.cancel();
|
2014-06-16 14:42:21 +02:00
|
|
|
delete m_qbsProjectParser;
|
2014-08-22 09:39:38 +02:00
|
|
|
if (m_qbsUpdateFutureInterface) {
|
|
|
|
|
m_qbsUpdateFutureInterface->reportCanceled();
|
2014-09-13 21:25:32 +03:00
|
|
|
m_qbsUpdateFutureInterface->reportFinished();
|
2014-08-22 09:39:38 +02:00
|
|
|
delete m_qbsUpdateFutureInterface;
|
|
|
|
|
m_qbsUpdateFutureInterface = 0;
|
|
|
|
|
}
|
2013-10-21 17:43:10 +02:00
|
|
|
|
|
|
|
|
// Deleting the root node triggers a few things, make sure rootProjectNode
|
|
|
|
|
// returns 0 already
|
|
|
|
|
QbsProjectNode *root = m_rootProjectNode;
|
|
|
|
|
m_rootProjectNode = 0;
|
|
|
|
|
delete root;
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString QbsProject::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_projectName;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 17:56:28 +02:00
|
|
|
IDocument *QbsProject::document() const
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-08-29 17:56:28 +02:00
|
|
|
foreach (IDocument *doc, m_qbsDocuments) {
|
2013-07-04 13:30:26 +02:00
|
|
|
if (doc->filePath() == m_fileName)
|
2013-01-30 18:19:31 +01:00
|
|
|
return doc;
|
|
|
|
|
}
|
|
|
|
|
QTC_ASSERT(false, return 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QbsManager *QbsProject::projectManager() const
|
|
|
|
|
{
|
|
|
|
|
return m_manager;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
ProjectNode *QbsProject::rootProjectNode() const
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
return m_rootProjectNode;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-08 14:17:46 +02:00
|
|
|
static void collectFilesForProject(const qbs::ProjectData &project, QSet<QString> &result)
|
|
|
|
|
{
|
|
|
|
|
result.insert(project.location().fileName());
|
|
|
|
|
foreach (const qbs::ProductData &prd, project.products()) {
|
|
|
|
|
foreach (const qbs::GroupData &grp, prd.groups()) {
|
|
|
|
|
foreach (const QString &file, grp.allFilePaths())
|
|
|
|
|
result.insert(file);
|
|
|
|
|
result.insert(grp.location().fileName());
|
|
|
|
|
}
|
|
|
|
|
result.insert(prd.location().fileName());
|
|
|
|
|
}
|
|
|
|
|
foreach (const qbs::ProjectData &subProject, project.subProjects())
|
|
|
|
|
collectFilesForProject(subProject, result);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
QStringList QbsProject::files(Project::FilesMode fileMode) const
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(fileMode);
|
2014-09-12 17:38:12 +02:00
|
|
|
if (!m_qbsProject.isValid() || isParsing())
|
2013-10-08 14:17:46 +02:00
|
|
|
return QStringList();
|
2013-03-05 11:23:00 +01:00
|
|
|
QSet<QString> result;
|
2014-09-12 17:38:12 +02:00
|
|
|
collectFilesForProject(m_projectData, result);
|
|
|
|
|
result.unite(m_qbsProject.buildSystemFiles());
|
2013-03-05 11:23:00 +01:00
|
|
|
return result.toList();
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-24 12:18:29 +02:00
|
|
|
bool QbsProject::isProjectEditable() const
|
|
|
|
|
{
|
|
|
|
|
return m_qbsProject.isValid() && !isParsing() && !ProjectExplorer::BuildManager::isBuilding();
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-18 15:46:24 +02:00
|
|
|
class ChangeExpector
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
ChangeExpector(const QString &filePath, const QSet<Core::IDocument *> &documents)
|
|
|
|
|
: m_document(0)
|
|
|
|
|
{
|
|
|
|
|
foreach (Core::IDocument * const doc, documents) {
|
|
|
|
|
if (doc->filePath() == filePath) {
|
|
|
|
|
m_document = doc;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QTC_ASSERT(m_document, return);
|
|
|
|
|
Core::DocumentManager::expectFileChange(filePath);
|
|
|
|
|
m_wasInDocumentManager = Core::DocumentManager::removeDocument(m_document);
|
|
|
|
|
QTC_CHECK(m_wasInDocumentManager);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~ChangeExpector()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_document, return);
|
|
|
|
|
Core::DocumentManager::addDocument(m_document);
|
|
|
|
|
Core::DocumentManager::unexpectFileChange(m_document->filePath());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
Core::IDocument *m_document;
|
|
|
|
|
bool m_wasInDocumentManager;
|
|
|
|
|
};
|
|
|
|
|
|
2014-08-18 16:30:43 +02:00
|
|
|
bool QbsProject::ensureWriteableQbsFile(const QString &file)
|
|
|
|
|
{
|
|
|
|
|
// Ensure that the file is not read only
|
|
|
|
|
QFileInfo fi(file);
|
|
|
|
|
if (!fi.isWritable()) {
|
|
|
|
|
// Try via vcs manager
|
|
|
|
|
Core::IVersionControl *versionControl =
|
|
|
|
|
Core::VcsManager::findVersionControlForDirectory(fi.absolutePath());
|
|
|
|
|
if (!versionControl || !versionControl->vcsOpen(file)) {
|
|
|
|
|
bool makeWritable = QFile::setPermissions(file, fi.permissions() | QFile::WriteUser);
|
|
|
|
|
if (!makeWritable) {
|
|
|
|
|
QMessageBox::warning(Core::ICore::mainWindow(),
|
|
|
|
|
tr("Failed!"),
|
|
|
|
|
tr("Could not write project file %1.").arg(file));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-18 15:46:24 +02:00
|
|
|
bool QbsProject::addFilesToProduct(QbsBaseProjectNode *node, const QStringList &filePaths,
|
|
|
|
|
const qbs::ProductData &productData, const qbs::GroupData &groupData, QStringList *notAdded)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_qbsProject.isValid(), return false);
|
|
|
|
|
QStringList allPaths = groupData.allFilePaths();
|
|
|
|
|
const QString productFilePath = productData.location().fileName();
|
|
|
|
|
ChangeExpector expector(productFilePath, m_qbsDocuments);
|
2014-08-18 16:30:43 +02:00
|
|
|
ensureWriteableQbsFile(productFilePath);
|
2014-07-18 15:46:24 +02:00
|
|
|
foreach (const QString &path, filePaths) {
|
|
|
|
|
qbs::ErrorInfo err = m_qbsProject.addFiles(productData, groupData, QStringList() << path);
|
|
|
|
|
if (err.hasError()) {
|
|
|
|
|
Core::MessageManager::write(err.toString());
|
|
|
|
|
*notAdded += path;
|
|
|
|
|
} else {
|
|
|
|
|
allPaths += path;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (notAdded->count() != filePaths.count()) {
|
|
|
|
|
m_projectData = m_qbsProject.projectData();
|
|
|
|
|
QbsGroupNode::setupFiles(node, allPaths, QFileInfo(productFilePath).absolutePath(), true);
|
2014-08-01 15:45:05 +02:00
|
|
|
m_rootProjectNode->update();
|
2014-07-18 15:46:24 +02:00
|
|
|
}
|
|
|
|
|
return notAdded->isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool QbsProject::removeFilesFromProduct(QbsBaseProjectNode *node, const QStringList &filePaths,
|
|
|
|
|
const qbs::ProductData &productData, const qbs::GroupData &groupData,
|
|
|
|
|
QStringList *notRemoved)
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_qbsProject.isValid(), return false);
|
|
|
|
|
QStringList allPaths = groupData.allFilePaths();
|
|
|
|
|
const QString productFilePath = productData.location().fileName();
|
|
|
|
|
ChangeExpector expector(productFilePath, m_qbsDocuments);
|
2014-08-18 16:30:43 +02:00
|
|
|
ensureWriteableQbsFile(productFilePath);
|
2014-07-18 15:46:24 +02:00
|
|
|
foreach (const QString &path, filePaths) {
|
|
|
|
|
qbs::ErrorInfo err
|
|
|
|
|
= m_qbsProject.removeFiles(productData, groupData, QStringList() << path);
|
|
|
|
|
if (err.hasError()) {
|
|
|
|
|
Core::MessageManager::write(err.toString());
|
|
|
|
|
*notRemoved += path;
|
|
|
|
|
} else {
|
|
|
|
|
allPaths.removeOne(path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (notRemoved->count() != filePaths.count()) {
|
|
|
|
|
m_projectData = m_qbsProject.projectData();
|
|
|
|
|
QbsGroupNode::setupFiles(node, allPaths, QFileInfo(productFilePath).absolutePath(), true);
|
2014-08-01 15:45:05 +02:00
|
|
|
m_rootProjectNode->update();
|
2014-07-18 15:46:24 +02:00
|
|
|
}
|
|
|
|
|
return notRemoved->isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
void QbsProject::invalidate()
|
|
|
|
|
{
|
|
|
|
|
prepareForParsing();
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-10 15:40:18 +02:00
|
|
|
qbs::BuildJob *QbsProject::build(const qbs::BuildOptions &opts, QStringList productNames)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-09-06 18:02:46 +02:00
|
|
|
if (!qbsProject().isValid() || isParsing())
|
2013-01-30 18:19:31 +01:00
|
|
|
return 0;
|
2013-06-10 15:40:18 +02:00
|
|
|
if (productNames.isEmpty()) {
|
2013-09-06 18:02:46 +02:00
|
|
|
return qbsProject().buildAllProducts(opts);
|
2013-06-10 15:40:18 +02:00
|
|
|
} else {
|
|
|
|
|
QList<qbs::ProductData> products;
|
|
|
|
|
foreach (const QString &productName, productNames) {
|
|
|
|
|
bool found = false;
|
2013-06-21 15:09:01 +02:00
|
|
|
foreach (const qbs::ProductData &data, qbsProjectData().allProducts()) {
|
2013-06-10 15:40:18 +02:00
|
|
|
if (data.name() == productName) {
|
|
|
|
|
found = true;
|
|
|
|
|
products.append(data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!found)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-06 18:02:46 +02:00
|
|
|
return qbsProject().buildSomeProducts(products, opts);
|
2013-06-10 15:40:18 +02:00
|
|
|
}
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-02-28 13:06:15 +01:00
|
|
|
qbs::CleanJob *QbsProject::clean(const qbs::CleanOptions &opts)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-09-06 18:02:46 +02:00
|
|
|
if (!qbsProject().isValid())
|
2013-01-30 18:19:31 +01:00
|
|
|
return 0;
|
2013-09-06 18:02:46 +02:00
|
|
|
return qbsProject().cleanAllProducts(opts);
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-04-12 16:19:52 +02:00
|
|
|
qbs::InstallJob *QbsProject::install(const qbs::InstallOptions &opts)
|
|
|
|
|
{
|
2013-09-06 18:02:46 +02:00
|
|
|
if (!qbsProject().isValid())
|
2013-04-12 16:19:52 +02:00
|
|
|
return 0;
|
2013-09-06 18:02:46 +02:00
|
|
|
return qbsProject().installAllProducts(opts);
|
2013-04-12 16:19:52 +02:00
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
QString QbsProject::profileForTarget(const Target *t) const
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
return m_manager->profileForKit(t->kit());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool QbsProject::isParsing() const
|
|
|
|
|
{
|
|
|
|
|
return m_qbsUpdateFutureInterface;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool QbsProject::hasParseResult() const
|
|
|
|
|
{
|
2013-09-06 18:02:46 +02:00
|
|
|
return qbsProject().isValid();
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2014-05-02 11:44:32 +02:00
|
|
|
Utils::FileName QbsProject::defaultBuildDirectory(const QString &projectFilePath, const Kit *k,
|
|
|
|
|
const QString &bcName)
|
2013-07-22 15:53:57 +02:00
|
|
|
{
|
2014-05-02 11:44:32 +02:00
|
|
|
const QString projectName = QFileInfo(projectFilePath).completeBaseName();
|
|
|
|
|
ProjectExplorer::ProjectMacroExpander expander(projectFilePath, projectName, k, bcName);
|
2014-05-02 12:53:36 +02:00
|
|
|
QString projectDir = projectDirectory(Utils::FileName::fromString(projectFilePath)).toString();
|
2014-05-02 11:44:32 +02:00
|
|
|
QString buildPath = Utils::expandMacros(Core::DocumentManager::buildDirectory(), &expander);
|
|
|
|
|
return Utils::FileName::fromString(Utils::FileUtils::resolvePath(projectDir, buildPath));
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-09-06 18:02:46 +02:00
|
|
|
qbs::Project QbsProject::qbsProject() const
|
2013-04-16 13:14:07 +02:00
|
|
|
{
|
2014-07-10 17:01:54 +02:00
|
|
|
return m_qbsProject;
|
2013-04-16 13:14:07 +02:00
|
|
|
}
|
|
|
|
|
|
2014-07-22 09:49:51 +02:00
|
|
|
qbs::ProjectData QbsProject::qbsProjectData() const
|
2013-04-16 13:14:07 +02:00
|
|
|
{
|
2014-07-22 09:49:51 +02:00
|
|
|
return m_projectData;
|
2013-04-16 13:14:07 +02:00
|
|
|
}
|
|
|
|
|
|
2013-05-06 11:16:41 +02:00
|
|
|
bool QbsProject::needsSpecialDeployment() const
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
void QbsProject::handleQbsParsingDone(bool success)
|
|
|
|
|
{
|
2014-06-16 14:42:21 +02:00
|
|
|
QTC_ASSERT(m_qbsProjectParser, return);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2014-07-14 14:22:27 +02:00
|
|
|
const CancelStatus cancelStatus = m_cancelStatus;
|
|
|
|
|
m_cancelStatus = CancelStatusNone;
|
|
|
|
|
|
|
|
|
|
// Start a new one parse operation right away, ignoring the old result.
|
|
|
|
|
if (cancelStatus == CancelStatusCancelingForReparse) {
|
2014-07-14 10:22:37 +02:00
|
|
|
m_qbsProjectParser->deleteLater();
|
|
|
|
|
m_qbsProjectParser = 0;
|
2014-07-17 12:02:56 +02:00
|
|
|
parseCurrentBuildConfiguration();
|
2014-07-14 10:22:37 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-16 14:42:21 +02:00
|
|
|
generateErrors(m_qbsProjectParser->error());
|
|
|
|
|
|
2014-07-10 17:01:54 +02:00
|
|
|
if (success) {
|
|
|
|
|
m_qbsProject = m_qbsProjectParser->qbsProject();
|
2014-07-17 12:33:03 +02:00
|
|
|
const qbs::ProjectData &projectData = m_qbsProject.projectData();
|
2014-07-10 17:01:54 +02:00
|
|
|
QTC_CHECK(m_qbsProject.isValid());
|
2014-07-17 12:33:03 +02:00
|
|
|
if (projectData != m_projectData) {
|
|
|
|
|
m_projectData = projectData;
|
|
|
|
|
readQbsData();
|
|
|
|
|
}
|
2014-07-14 10:22:37 +02:00
|
|
|
} else {
|
|
|
|
|
m_qbsUpdateFutureInterface->reportCanceled();
|
2014-07-10 17:01:54 +02:00
|
|
|
}
|
|
|
|
|
|
2014-06-16 14:42:21 +02:00
|
|
|
m_qbsProjectParser->deleteLater();
|
|
|
|
|
m_qbsProjectParser = 0;
|
|
|
|
|
|
|
|
|
|
if (m_qbsUpdateFutureInterface) {
|
|
|
|
|
m_qbsUpdateFutureInterface->reportFinished();
|
|
|
|
|
delete m_qbsUpdateFutureInterface;
|
|
|
|
|
m_qbsUpdateFutureInterface = 0;
|
|
|
|
|
}
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
emit projectParsingDone(success);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
void QbsProject::targetWasAdded(Target *t)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
connect(t, SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
|
2014-07-17 12:02:56 +02:00
|
|
|
this, SLOT(delayParsing()));
|
|
|
|
|
connect(t, SIGNAL(buildDirectoryChanged()), this, SLOT(delayParsing()));
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
void QbsProject::changeActiveTarget(Target *t)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-08-29 18:25:59 +02:00
|
|
|
BuildConfiguration *bc = 0;
|
2013-01-30 18:19:31 +01:00
|
|
|
if (t && t->kit())
|
|
|
|
|
bc = t->activeBuildConfiguration();
|
|
|
|
|
buildConfigurationChanged(bc);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
void QbsProject::buildConfigurationChanged(BuildConfiguration *bc)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
if (m_currentBc)
|
2013-06-06 18:45:53 +02:00
|
|
|
disconnect(m_currentBc, SIGNAL(qbsConfigurationChanged()), this, SLOT(delayParsing()));
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
m_currentBc = qobject_cast<QbsBuildConfiguration *>(bc);
|
|
|
|
|
if (m_currentBc) {
|
2013-06-06 18:45:53 +02:00
|
|
|
connect(m_currentBc, SIGNAL(qbsConfigurationChanged()), this, SLOT(delayParsing()));
|
|
|
|
|
delayParsing();
|
2013-01-30 18:19:31 +01:00
|
|
|
} else {
|
|
|
|
|
invalidate();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-26 16:19:43 +01:00
|
|
|
void QbsProject::startParsing()
|
|
|
|
|
{
|
2014-03-03 14:15:46 +01:00
|
|
|
// Qbs does update the build graph during the build. So we cannot
|
|
|
|
|
// start to parse while a build is running or we will lose information.
|
2014-07-14 14:22:27 +02:00
|
|
|
if (ProjectExplorer::BuildManager::isBuilding(this)) {
|
|
|
|
|
scheduleParsing();
|
2014-03-03 14:15:46 +01:00
|
|
|
return;
|
2014-07-14 14:22:27 +02:00
|
|
|
}
|
2014-03-03 14:15:46 +01:00
|
|
|
|
2014-07-17 12:02:56 +02:00
|
|
|
parseCurrentBuildConfiguration();
|
2013-11-26 16:19:43 +01:00
|
|
|
}
|
|
|
|
|
|
2013-06-06 18:45:53 +02:00
|
|
|
void QbsProject::delayParsing()
|
|
|
|
|
{
|
|
|
|
|
m_parsingDelay.start();
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-24 12:06:13 +02:00
|
|
|
// Qbs may change its data
|
|
|
|
|
void QbsProject::readQbsData()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_rootProjectNode, return);
|
|
|
|
|
|
|
|
|
|
m_rootProjectNode->update();
|
|
|
|
|
|
|
|
|
|
qbs::Project project = m_rootProjectNode->qbsProject();
|
|
|
|
|
updateDocuments(project.isValid() ? project.buildSystemFiles() : QSet<QString>() << m_fileName);
|
|
|
|
|
|
|
|
|
|
qbs::ProjectData data = m_rootProjectNode->qbsProjectData();
|
|
|
|
|
updateCppCodeModel(data);
|
|
|
|
|
updateQmlJsCodeModel(data);
|
2014-07-11 12:44:12 +02:00
|
|
|
updateBuildTargetData();
|
2014-06-24 12:06:13 +02:00
|
|
|
|
|
|
|
|
emit fileListChanged();
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-17 12:02:56 +02:00
|
|
|
void QbsProject::parseCurrentBuildConfiguration()
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2014-07-11 12:44:12 +02:00
|
|
|
m_parsingScheduled = false;
|
2014-07-14 14:22:27 +02:00
|
|
|
if (m_cancelStatus == CancelStatusCancelingForReparse)
|
2014-07-14 10:22:37 +02:00
|
|
|
return;
|
2013-11-26 16:19:43 +01:00
|
|
|
|
2014-07-14 14:22:27 +02:00
|
|
|
// The CancelStatusCancelingAltoghether type can only be set by a build job, during
|
|
|
|
|
// which no other parse requests come through to this point (except by the build job itself,
|
|
|
|
|
// but of course not while canceling is in progress).
|
|
|
|
|
QTC_ASSERT(m_cancelStatus == CancelStatusNone, return);
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
if (!activeTarget())
|
|
|
|
|
return;
|
|
|
|
|
QbsBuildConfiguration *bc = qobject_cast<QbsBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
|
|
|
|
|
if (!bc)
|
|
|
|
|
return;
|
2014-07-14 10:22:37 +02:00
|
|
|
|
|
|
|
|
// New parse requests override old ones.
|
|
|
|
|
// NOTE: We need to wait for the current operation to finish, since otherwise there could
|
|
|
|
|
// be a conflict. Consider the case where the old qbs::ProjectSetupJob is writing
|
|
|
|
|
// to the build graph file when the cancel request comes in. If we don't wait for
|
|
|
|
|
// acknowledgment, it might still be doing that when the new one already reads from the
|
|
|
|
|
// same file.
|
|
|
|
|
if (m_qbsProjectParser) {
|
2014-07-14 14:22:27 +02:00
|
|
|
m_cancelStatus = CancelStatusCancelingForReparse;
|
2014-07-14 10:22:37 +02:00
|
|
|
m_qbsProjectParser->cancel();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-16 17:45:16 +02:00
|
|
|
parse(bc->qbsConfiguration(), bc->environment(), bc->buildDirectory().toString());
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2014-07-14 14:22:27 +02:00
|
|
|
void QbsProject::cancelParsing()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(m_qbsProjectParser, return);
|
|
|
|
|
m_cancelStatus = CancelStatusCancelingAltoghether;
|
|
|
|
|
m_qbsProjectParser->cancel();
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-11 12:44:12 +02:00
|
|
|
void QbsProject::updateAfterBuild()
|
|
|
|
|
{
|
2014-07-28 09:53:06 +02:00
|
|
|
QTC_ASSERT(m_qbsProject.isValid(), return);
|
|
|
|
|
m_projectData = m_qbsProject.projectData();
|
2014-07-11 12:44:12 +02:00
|
|
|
updateBuildTargetData();
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-16 14:42:21 +02:00
|
|
|
void QbsProject::registerQbsProjectParser(QbsProjectParser *p)
|
|
|
|
|
{
|
|
|
|
|
m_parsingDelay.stop();
|
|
|
|
|
|
|
|
|
|
if (m_qbsProjectParser) {
|
|
|
|
|
m_qbsProjectParser->disconnect(this);
|
|
|
|
|
m_qbsProjectParser->deleteLater();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_qbsProjectParser = p;
|
|
|
|
|
|
2014-07-17 12:02:56 +02:00
|
|
|
if (p)
|
2014-06-16 14:42:21 +02:00
|
|
|
connect(m_qbsProjectParser, SIGNAL(done(bool)), this, SLOT(handleQbsParsingDone(bool)));
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
bool QbsProject::fromMap(const QVariantMap &map)
|
|
|
|
|
{
|
|
|
|
|
if (!Project::fromMap(map))
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
Kit *defaultKit = KitManager::defaultKit();
|
2013-08-21 12:48:46 +02:00
|
|
|
if (!activeTarget() && defaultKit) {
|
2013-08-29 18:25:59 +02:00
|
|
|
Target *t = new Target(this, defaultKit);
|
2013-01-30 18:19:31 +01:00
|
|
|
t->updateDefaultBuildConfigurations();
|
|
|
|
|
t->updateDefaultDeployConfigurations();
|
|
|
|
|
t->updateDefaultRunConfigurations();
|
|
|
|
|
addTarget(t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 12:06:11 +02:00
|
|
|
void QbsProject::generateErrors(const qbs::ErrorInfo &e)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-06-18 12:06:11 +02:00
|
|
|
foreach (const qbs::ErrorItem &item, e.items())
|
2013-08-29 18:25:59 +02:00
|
|
|
TaskHub::addTask(Task::Error, item.description(),
|
|
|
|
|
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM,
|
|
|
|
|
FileName::fromString(item.codeLocation().fileName()),
|
|
|
|
|
item.codeLocation().line());
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-08-29 18:25:59 +02:00
|
|
|
void QbsProject::parse(const QVariantMap &config, const Environment &env, const QString &dir)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-06-11 18:10:42 +02:00
|
|
|
prepareForParsing();
|
2014-06-16 14:42:21 +02:00
|
|
|
QTC_ASSERT(!m_qbsProjectParser, return);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2014-06-16 14:42:21 +02:00
|
|
|
registerQbsProjectParser(new QbsProjectParser(this, m_qbsUpdateFutureInterface));
|
2013-05-30 14:14:42 +02:00
|
|
|
|
2014-07-17 12:02:56 +02:00
|
|
|
m_qbsProjectParser->parse(config, env, dir);
|
|
|
|
|
emit projectParsingStarted();
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void QbsProject::prepareForParsing()
|
|
|
|
|
{
|
2013-08-29 18:25:59 +02:00
|
|
|
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
2013-11-15 15:24:11 +01:00
|
|
|
if (m_qbsUpdateFutureInterface) {
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsUpdateFutureInterface->reportCanceled();
|
2013-11-15 15:24:11 +01:00
|
|
|
m_qbsUpdateFutureInterface->reportFinished();
|
|
|
|
|
}
|
2013-01-30 18:19:31 +01:00
|
|
|
delete m_qbsUpdateFutureInterface;
|
|
|
|
|
m_qbsUpdateFutureInterface = 0;
|
|
|
|
|
|
2014-06-16 14:42:21 +02:00
|
|
|
m_qbsUpdateFutureInterface = new QFutureInterface<bool>();
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsUpdateFutureInterface->setProgressRange(0, 0);
|
2013-09-03 15:18:37 +02:00
|
|
|
ProgressManager::addTask(m_qbsUpdateFutureInterface->future(),
|
2014-04-17 15:14:14 +02:00
|
|
|
tr("Reading Project \"%1\"").arg(displayName()), "Qbs.QbsEvaluate");
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsUpdateFutureInterface->reportStarted();
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-18 15:52:29 +02:00
|
|
|
void QbsProject::updateDocuments(const QSet<QString> &files)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
// Update documents:
|
2013-06-18 15:52:29 +02:00
|
|
|
QSet<QString> newFiles = files;
|
|
|
|
|
QTC_ASSERT(!newFiles.isEmpty(), newFiles << m_fileName);
|
2013-01-30 18:19:31 +01:00
|
|
|
QSet<QString> oldFiles;
|
2013-08-29 17:56:28 +02:00
|
|
|
foreach (IDocument *doc, m_qbsDocuments)
|
2013-07-04 13:30:26 +02:00
|
|
|
oldFiles.insert(doc->filePath());
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
QSet<QString> filesToAdd = newFiles;
|
|
|
|
|
filesToAdd.subtract(oldFiles);
|
|
|
|
|
QSet<QString> filesToRemove = oldFiles;
|
|
|
|
|
filesToRemove.subtract(newFiles);
|
|
|
|
|
|
2013-08-29 17:56:28 +02:00
|
|
|
QSet<IDocument *> currentDocuments = m_qbsDocuments;
|
|
|
|
|
foreach (IDocument *doc, currentDocuments) {
|
2013-07-04 13:30:26 +02:00
|
|
|
if (filesToRemove.contains(doc->filePath())) {
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsDocuments.remove(doc);
|
|
|
|
|
delete doc;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-08-29 17:56:28 +02:00
|
|
|
QSet<IDocument *> toAdd;
|
2013-01-30 18:19:31 +01:00
|
|
|
foreach (const QString &f, filesToAdd)
|
|
|
|
|
toAdd.insert(new QbsProjectFile(this, f));
|
|
|
|
|
|
2013-08-29 17:56:28 +02:00
|
|
|
DocumentManager::addDocuments(toAdd.toList());
|
2013-01-30 18:19:31 +01:00
|
|
|
m_qbsDocuments.unite(toAdd);
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-21 15:09:01 +02:00
|
|
|
void QbsProject::updateCppCodeModel(const qbs::ProjectData &prj)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
2013-06-21 15:09:01 +02:00
|
|
|
if (!prj.isValid())
|
2013-01-30 18:19:31 +01:00
|
|
|
return;
|
|
|
|
|
|
2014-08-19 12:01:47 +02:00
|
|
|
QtSupport::BaseQtVersion *qtVersion =
|
|
|
|
|
QtSupport::QtKitInformation::qtVersion(activeTarget()->kit());
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-04-02 11:28:11 +02:00
|
|
|
CppTools::CppModelManagerInterface *modelmanager =
|
|
|
|
|
CppTools::CppModelManagerInterface::instance();
|
2013-01-30 18:19:31 +01:00
|
|
|
|
|
|
|
|
if (!modelmanager)
|
|
|
|
|
return;
|
|
|
|
|
|
2014-07-30 17:13:45 +02:00
|
|
|
CppTools::ProjectInfo pinfo = modelmanager->projectInfo(this);
|
2013-01-30 18:19:31 +01:00
|
|
|
pinfo.clearProjectParts();
|
2014-08-19 12:01:47 +02:00
|
|
|
|
|
|
|
|
CppTools::ProjectPartBuilder ppBuilder(pinfo);
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
if (qtVersion) {
|
|
|
|
|
if (qtVersion->qtVersion() < QtSupport::QtVersionNumber(5,0,0))
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setQtVersion(CppTools::ProjectPart::Qt4);
|
2013-01-30 18:19:31 +01:00
|
|
|
else
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setQtVersion(CppTools::ProjectPart::Qt5);
|
|
|
|
|
} else {
|
|
|
|
|
ppBuilder.setQtVersion(CppTools::ProjectPart::NoQt);
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-08-07 12:29:52 +02:00
|
|
|
QHash<QString, QString> uiFiles;
|
2013-06-21 15:09:01 +02:00
|
|
|
foreach (const qbs::ProductData &prd, prj.allProducts()) {
|
2013-01-30 18:19:31 +01:00
|
|
|
foreach (const qbs::GroupData &grp, prd.groups()) {
|
2013-02-20 17:40:52 +01:00
|
|
|
const qbs::PropertyMap &props = grp.properties();
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setCxxFlags(props.getModulePropertiesAsStringList(
|
|
|
|
|
QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_CXXFLAGS)));
|
|
|
|
|
ppBuilder.setCFlags(props.getModulePropertiesAsStringList(
|
|
|
|
|
QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_CFLAGS)));
|
2013-04-28 17:18:50 +04:00
|
|
|
|
2013-02-20 17:40:52 +01:00
|
|
|
QStringList list = props.getModulePropertiesAsStringList(
|
|
|
|
|
QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_DEFINES));
|
2013-04-28 17:15:51 +04:00
|
|
|
QByteArray grpDefines;
|
2013-03-21 13:17:51 +01:00
|
|
|
foreach (const QString &def, list) {
|
|
|
|
|
QByteArray data = def.toUtf8();
|
|
|
|
|
int pos = data.indexOf('=');
|
|
|
|
|
if (pos >= 0)
|
|
|
|
|
data[pos] = ' ';
|
|
|
|
|
grpDefines += (QByteArray("#define ") + data + '\n');
|
|
|
|
|
}
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setDefines(grpDefines);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-02-20 17:40:52 +01:00
|
|
|
list = props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_INCLUDEPATHS));
|
2014-07-23 10:48:29 +02:00
|
|
|
list.append(props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_SYSTEM_INCLUDEPATHS)));
|
2014-06-25 17:23:19 +02:00
|
|
|
CppTools::ProjectPart::HeaderPaths grpHeaderPaths;
|
|
|
|
|
foreach (const QString &p, list)
|
|
|
|
|
grpHeaderPaths += CppTools::ProjectPart::HeaderPath(
|
|
|
|
|
FileName::fromUserInput(p).toString(),
|
|
|
|
|
CppTools::ProjectPart::HeaderPath::IncludePath);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-02-20 17:40:52 +01:00
|
|
|
list = props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_FRAMEWORKPATHS));
|
2014-07-23 10:48:29 +02:00
|
|
|
list.append(props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_SYSTEM_FRAMEWORKPATHS)));
|
2014-06-25 17:23:19 +02:00
|
|
|
foreach (const QString &p, list)
|
|
|
|
|
grpHeaderPaths += CppTools::ProjectPart::HeaderPath(
|
|
|
|
|
FileName::fromUserInput(p).toString(),
|
|
|
|
|
CppTools::ProjectPart::HeaderPath::FrameworkPath);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setHeaderPaths(grpHeaderPaths);
|
|
|
|
|
|
2013-02-20 17:40:52 +01:00
|
|
|
const QString pch = props.getModuleProperty(QLatin1String(CONFIG_CPP_MODULE),
|
|
|
|
|
QLatin1String(CONFIG_PRECOMPILEDHEADER)).toString();
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setPreCompiledHeaders(QStringList() << pch);
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2014-08-19 12:01:47 +02:00
|
|
|
ppBuilder.setDisplayName(grp.name());
|
|
|
|
|
ppBuilder.setProjectFile(QString::fromLatin1("%1:%2:%3")
|
2013-09-30 15:59:49 +02:00
|
|
|
.arg(grp.location().fileName())
|
|
|
|
|
.arg(grp.location().line())
|
2014-08-19 12:01:47 +02:00
|
|
|
.arg(grp.location().column()));
|
2013-04-28 17:15:51 +04:00
|
|
|
|
2013-08-07 12:29:52 +02:00
|
|
|
foreach (const QString &file, grp.allFilePaths()) {
|
|
|
|
|
if (file.endsWith(QLatin1String(".ui"))) {
|
|
|
|
|
QStringList generated = m_rootProjectNode->qbsProject()
|
2013-09-06 18:02:46 +02:00
|
|
|
.generatedFiles(prd, file, QStringList(QLatin1String("hpp")));
|
2013-08-07 12:29:52 +02:00
|
|
|
if (generated.count() == 1)
|
|
|
|
|
uiFiles.insert(file, generated.at(0));
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-08-19 12:01:47 +02:00
|
|
|
|
|
|
|
|
const QList<Core::Id> languages =
|
|
|
|
|
ppBuilder.createProjectPartsForFiles(grp.allFilePaths());
|
|
|
|
|
foreach (Core::Id language, languages)
|
|
|
|
|
setProjectLanguage(language, true);
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pinfo.projectParts().isEmpty())
|
|
|
|
|
return;
|
2014-09-12 14:14:18 +02:00
|
|
|
pinfo.finish();
|
2013-01-30 18:19:31 +01:00
|
|
|
|
2013-08-07 12:29:52 +02:00
|
|
|
QtSupport::UiCodeModelManager::update(this, uiFiles);
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
// Register update the code model:
|
2013-07-16 12:08:39 +02:00
|
|
|
m_codeModelFuture = modelmanager->updateProjectInfo(pinfo);
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-06-21 15:09:01 +02:00
|
|
|
void QbsProject::updateQmlJsCodeModel(const qbs::ProjectData &prj)
|
2013-01-30 18:19:31 +01:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(prj);
|
2013-02-22 11:20:33 +01:00
|
|
|
QmlJS::ModelManagerInterface *modelManager = QmlJS::ModelManagerInterface::instance();
|
|
|
|
|
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);
|
2013-04-10 14:45:47 +02:00
|
|
|
|
|
|
|
|
setProjectLanguage(ProjectExplorer::Constants::LANG_QMLJS, !projectInfo.sourceFiles.isEmpty());
|
2014-01-23 14:28:31 +01:00
|
|
|
modelManager->updateProjectInfo(projectInfo, this);
|
2013-01-30 18:19:31 +01:00
|
|
|
}
|
|
|
|
|
|
2013-09-02 10:12:37 +02:00
|
|
|
void QbsProject::updateApplicationTargets(const qbs::ProjectData &projectData)
|
|
|
|
|
{
|
|
|
|
|
ProjectExplorer::BuildTargetInfoList applications;
|
|
|
|
|
foreach (const qbs::ProductData &productData, projectData.allProducts()) {
|
2014-08-07 15:38:38 +02:00
|
|
|
if (!productData.isEnabled() || !productData.isRunnable())
|
|
|
|
|
continue;
|
|
|
|
|
if (productData.targetArtifacts().isEmpty()) { // No build yet.
|
2014-08-07 15:53:54 +02:00
|
|
|
applications.list << ProjectExplorer::BuildTargetInfo(productData.name(),
|
|
|
|
|
Utils::FileName(),
|
2014-08-07 15:38:38 +02:00
|
|
|
Utils::FileName::fromString(productData.location().fileName()));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2013-09-02 10:12:37 +02:00
|
|
|
foreach (const qbs::TargetArtifact &ta, productData.targetArtifacts()) {
|
|
|
|
|
QTC_ASSERT(ta.isValid(), continue);
|
|
|
|
|
if (!ta.isExecutable())
|
|
|
|
|
continue;
|
2014-08-07 15:53:54 +02:00
|
|
|
applications.list << ProjectExplorer::BuildTargetInfo(productData.name(),
|
|
|
|
|
Utils::FileName::fromString(ta.filePath()),
|
2013-09-02 10:12:37 +02:00
|
|
|
Utils::FileName::fromString(productData.location().fileName()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
activeTarget()->setApplicationTargets(applications);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-06 18:02:46 +02:00
|
|
|
void QbsProject::updateDeploymentInfo(const qbs::Project &project)
|
2013-09-02 10:12:37 +02:00
|
|
|
{
|
|
|
|
|
ProjectExplorer::DeploymentData deploymentData;
|
2013-09-06 18:02:46 +02:00
|
|
|
if (project.isValid()) {
|
2013-09-02 10:12:37 +02:00
|
|
|
qbs::InstallOptions installOptions;
|
|
|
|
|
installOptions.setInstallRoot(QLatin1String("/"));
|
|
|
|
|
foreach (const qbs::InstallableFile &f,
|
2014-07-28 09:53:06 +02:00
|
|
|
project.installableFilesForProject(m_projectData, installOptions)) {
|
2013-09-02 10:12:37 +02:00
|
|
|
deploymentData.addFile(f.sourceFilePath(), f.targetDirectory(), f.isExecutable()
|
|
|
|
|
? ProjectExplorer::DeployableFile::TypeExecutable
|
|
|
|
|
: ProjectExplorer::DeployableFile::TypeNormal);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
activeTarget()->setDeploymentData(deploymentData);
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-11 12:44:12 +02:00
|
|
|
void QbsProject::updateBuildTargetData()
|
|
|
|
|
{
|
2014-07-28 09:53:06 +02:00
|
|
|
updateApplicationTargets(m_projectData);
|
2014-07-11 12:44:12 +02:00
|
|
|
updateDeploymentInfo(m_qbsProject);
|
|
|
|
|
foreach (Target *t, targets())
|
|
|
|
|
t->updateDefaultRunConfigurations();
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-30 18:19:31 +01:00
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace QbsProjectManager
|