2019-08-09 11:22:49 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2019 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator.
|
|
|
|
|
**
|
|
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
|
**
|
|
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "buildsystem.h"
|
|
|
|
|
|
|
|
|
|
#include "buildconfiguration.h"
|
2019-10-25 09:55:32 +02:00
|
|
|
#include "runconfiguration.h"
|
|
|
|
|
#include "runcontrol.h"
|
2019-08-09 11:22:49 +02:00
|
|
|
#include "target.h"
|
|
|
|
|
|
|
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
#include <QTimer>
|
|
|
|
|
|
2019-08-09 11:22:49 +02:00
|
|
|
using namespace Utils;
|
|
|
|
|
|
|
|
|
|
namespace ProjectExplorer {
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// BuildSystem:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
class BuildSystemPrivate
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
Target *m_target = nullptr;
|
|
|
|
|
BuildConfiguration *m_buildConfiguration = nullptr;
|
|
|
|
|
|
|
|
|
|
QTimer m_delayedParsingTimer;
|
|
|
|
|
|
|
|
|
|
bool m_isParsing = false;
|
|
|
|
|
bool m_hasParsingData = false;
|
|
|
|
|
|
|
|
|
|
DeploymentData m_deploymentData;
|
|
|
|
|
QList<BuildTargetInfo> m_appTargets;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
BuildSystem::BuildSystem(BuildConfiguration *bc)
|
|
|
|
|
: BuildSystem(bc->target())
|
|
|
|
|
{
|
|
|
|
|
d->m_buildConfiguration = bc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildSystem::BuildSystem(Target *target)
|
|
|
|
|
: d(new BuildSystemPrivate)
|
2019-08-09 11:22:49 +02:00
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
QTC_CHECK(target);
|
|
|
|
|
d->m_target = target;
|
2019-08-09 11:22:49 +02:00
|
|
|
|
|
|
|
|
// Timer:
|
2019-10-25 09:55:32 +02:00
|
|
|
d->m_delayedParsingTimer.setSingleShot(true);
|
2019-08-09 11:22:49 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
connect(&d->m_delayedParsingTimer, &QTimer::timeout, this, &BuildSystem::triggerParsing);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildSystem::~BuildSystem()
|
|
|
|
|
{
|
|
|
|
|
delete d;
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Project *BuildSystem::project() const
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_target->project();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Target *BuildSystem::target() const
|
|
|
|
|
{
|
|
|
|
|
return d->m_target;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::emitParsingStarted()
|
|
|
|
|
{
|
|
|
|
|
QTC_ASSERT(!d->m_isParsing, return);
|
|
|
|
|
|
|
|
|
|
d->m_isParsing = true;
|
|
|
|
|
d->m_hasParsingData = false;
|
|
|
|
|
emit d->m_target->parsingStarted();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::emitParsingFinished(bool success)
|
|
|
|
|
{
|
|
|
|
|
// Intentionally no return, as we currently get start - start - end - end
|
|
|
|
|
// sequences when switching qmake targets quickly.
|
|
|
|
|
QTC_CHECK(d->m_isParsing);
|
|
|
|
|
|
|
|
|
|
d->m_isParsing = false;
|
|
|
|
|
d->m_hasParsingData = success;
|
|
|
|
|
emit d->m_target->parsingFinished(success);
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:55:51 +02:00
|
|
|
FilePath BuildSystem::projectFilePath() const
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_target->project()->projectFilePath();
|
2019-10-22 14:55:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilePath BuildSystem::projectDirectory() const
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_target->project()->projectDirectory();
|
2019-10-22 14:55:51 +02:00
|
|
|
}
|
|
|
|
|
|
2019-08-09 11:22:49 +02:00
|
|
|
bool BuildSystem::isWaitingForParse() const
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_delayedParsingTimer.isActive();
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::requestParse()
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
requestParseHelper(0);
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::requestDelayedParse()
|
|
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
requestParseHelper(1000);
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
bool BuildSystem::isParsing() const
|
2019-08-09 11:22:49 +02:00
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_isParsing;
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
bool BuildSystem::hasParsingData() const
|
2019-08-09 11:22:49 +02:00
|
|
|
{
|
2019-10-25 09:55:32 +02:00
|
|
|
return d->m_hasParsingData;
|
|
|
|
|
}
|
2019-08-09 11:22:49 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
Environment BuildSystem::activeParseEnvironment() const
|
|
|
|
|
{
|
|
|
|
|
const BuildConfiguration *const bc = d->m_target->activeBuildConfiguration();
|
2019-08-09 11:22:49 +02:00
|
|
|
if (bc)
|
2019-10-25 09:55:32 +02:00
|
|
|
return bc->environment();
|
2019-08-09 11:22:49 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
const RunConfiguration *const rc = d->m_target->activeRunConfiguration();
|
|
|
|
|
if (rc)
|
|
|
|
|
return rc->runnable().environment;
|
2019-08-09 11:22:49 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
Environment result = Utils::Environment::systemEnvironment();
|
|
|
|
|
d->m_target->kit()->addToEnvironment(result);
|
2019-08-09 11:22:49 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
return result;
|
|
|
|
|
}
|
2019-10-08 12:54:08 +02:00
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
void BuildSystem::requestParseHelper(int delay)
|
|
|
|
|
{
|
|
|
|
|
d->m_delayedParsingTimer.setInterval(delay);
|
|
|
|
|
d->m_delayedParsingTimer.start();
|
2019-08-09 11:22:49 +02:00
|
|
|
}
|
|
|
|
|
|
2019-10-22 14:55:51 +02:00
|
|
|
bool BuildSystem::addFiles(Node *, const QStringList &filePaths, QStringList *notAdded)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(filePaths)
|
|
|
|
|
Q_UNUSED(notAdded)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RemovedFilesFromProject BuildSystem::removeFiles(Node *, const QStringList &filePaths,
|
|
|
|
|
QStringList *notRemoved)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(filePaths)
|
|
|
|
|
Q_UNUSED(notRemoved)
|
|
|
|
|
return RemovedFilesFromProject::Error;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BuildSystem::deleteFiles(Node *, const QStringList &filePaths)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(filePaths)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BuildSystem::canRenameFile(Node *, const QString &filePath, const QString &newFilePath)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(filePath)
|
|
|
|
|
Q_UNUSED(newFilePath)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BuildSystem::renameFile(Node *, const QString &filePath, const QString &newFilePath)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(filePath)
|
|
|
|
|
Q_UNUSED(newFilePath)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BuildSystem::addDependencies(Node *, const QStringList &dependencies)
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(dependencies)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BuildSystem::supportsAction(Node *, ProjectAction, const Node *) const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-25 09:55:32 +02:00
|
|
|
QStringList BuildSystem::filesGeneratedFrom(const QString &sourceFile) const
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(sourceFile)
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariant BuildSystem::additionalData(Core::Id id) const
|
|
|
|
|
{
|
|
|
|
|
Q_UNUSED(id)
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ParseGuard
|
|
|
|
|
|
|
|
|
|
BuildSystem::ParseGuard::ParseGuard(BuildSystem::ParseGuard &&other)
|
|
|
|
|
: m_buildSystem{std::move(other.m_buildSystem)}
|
|
|
|
|
, m_success{std::move(other.m_success)}
|
|
|
|
|
{
|
|
|
|
|
// No need to release this as this is invalid anyway:-)
|
|
|
|
|
other.m_buildSystem = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildSystem::ParseGuard::ParseGuard(BuildSystem *p)
|
|
|
|
|
: m_buildSystem(p)
|
|
|
|
|
{
|
|
|
|
|
if (m_buildSystem && !m_buildSystem->isParsing())
|
|
|
|
|
m_buildSystem->emitParsingStarted();
|
|
|
|
|
else
|
|
|
|
|
m_buildSystem = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::ParseGuard::release()
|
|
|
|
|
{
|
|
|
|
|
if (m_buildSystem)
|
|
|
|
|
m_buildSystem->emitParsingFinished(m_success);
|
|
|
|
|
m_buildSystem = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildSystem::ParseGuard &BuildSystem::ParseGuard::operator=(BuildSystem::ParseGuard &&other)
|
|
|
|
|
{
|
|
|
|
|
release();
|
|
|
|
|
|
|
|
|
|
m_buildSystem = std::move(other.m_buildSystem);
|
|
|
|
|
m_success = std::move(other.m_success);
|
|
|
|
|
|
|
|
|
|
other.m_buildSystem = nullptr;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::setDeploymentData(const DeploymentData &deploymentData)
|
|
|
|
|
{
|
|
|
|
|
if (d->m_deploymentData != deploymentData) {
|
|
|
|
|
d->m_deploymentData = deploymentData;
|
|
|
|
|
emit deploymentDataChanged();
|
|
|
|
|
emit applicationTargetsChanged();
|
|
|
|
|
emit target()->deploymentDataChanged();
|
|
|
|
|
emit target()->applicationTargetsChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DeploymentData BuildSystem::deploymentData() const
|
|
|
|
|
{
|
|
|
|
|
return d->m_deploymentData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BuildSystem::setApplicationTargets(const QList<BuildTargetInfo> &appTargets)
|
|
|
|
|
{
|
|
|
|
|
if (Utils::toSet(appTargets) != Utils::toSet(d->m_appTargets)) {
|
|
|
|
|
d->m_appTargets = appTargets;
|
|
|
|
|
emit applicationTargetsChanged();
|
|
|
|
|
emit target()->applicationTargetsChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QList<BuildTargetInfo> BuildSystem::applicationTargets() const
|
|
|
|
|
{
|
|
|
|
|
return d->m_appTargets;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildTargetInfo BuildSystem::buildTarget(const QString &buildKey) const
|
|
|
|
|
{
|
|
|
|
|
return Utils::findOrDefault(d->m_appTargets, [&buildKey](const BuildTargetInfo &ti) {
|
|
|
|
|
return ti.buildKey == buildKey;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString BuildSystem::disabledReason(const QString &buildKey) const
|
|
|
|
|
{
|
|
|
|
|
if (hasParsingData()) {
|
|
|
|
|
QString msg = isParsing() ? tr("The project is currently being parsed.")
|
|
|
|
|
: tr("The project could not be fully parsed.");
|
|
|
|
|
const FilePath projectFilePath = buildTarget(buildKey).projectFilePath;
|
|
|
|
|
if (!projectFilePath.isEmpty() && !projectFilePath.exists())
|
|
|
|
|
msg += '\n' + tr("The project file \"%1\" does not exist.").arg(projectFilePath.toString());
|
|
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 11:22:49 +02:00
|
|
|
} // namespace ProjectExplorer
|