forked from qt-creator/qt-creator
CMake: Fix project parsing notification
This builds on top of 08677c0b01
and
fixes one more code path to go through a common entry/exit point.
Change-Id: I1d00fa9242f247028e5d3b0ef3b5fe1d3f4cb03d
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -58,18 +58,13 @@ namespace Internal {
|
||||
// BuildDirManager:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
|
||||
m_buildConfiguration(bc)
|
||||
{
|
||||
QTC_ASSERT(bc, return);
|
||||
}
|
||||
|
||||
BuildDirManager::BuildDirManager() = default;
|
||||
BuildDirManager::~BuildDirManager() = default;
|
||||
|
||||
const Utils::FileName BuildDirManager::workDirectory() const
|
||||
Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters ¶meters) const
|
||||
{
|
||||
const Utils::FileName bdir = m_buildConfiguration->buildDirectory();
|
||||
const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
|
||||
const Utils::FileName bdir = parameters.buildDirectory;
|
||||
const CMakeTool *cmake = parameters.cmakeTool;
|
||||
if (bdir.exists()) {
|
||||
return bdir;
|
||||
} else {
|
||||
@@ -102,21 +97,21 @@ void BuildDirManager::emitErrorOccured(const QString &message) const
|
||||
m_isHandlingError = false;
|
||||
}
|
||||
|
||||
void BuildDirManager::updateReaderType(std::function<void()> todo)
|
||||
void BuildDirManager::updateReaderType(const BuildDirParameters &p,
|
||||
std::function<void()> todo)
|
||||
{
|
||||
BuildDirReader::Parameters p(m_buildConfiguration);
|
||||
p.buildDirectory = workDirectory();
|
||||
|
||||
if (!m_reader || !m_reader->isCompatible(p)) {
|
||||
m_reader.reset(BuildDirReader::createReader(p));
|
||||
connect(m_reader.get(), &BuildDirReader::configurationStarted,
|
||||
this, &BuildDirManager::configurationStarted);
|
||||
this, &BuildDirManager::parsingStarted);
|
||||
connect(m_reader.get(), &BuildDirReader::dataAvailable,
|
||||
this, &BuildDirManager::emitDataAvailable);
|
||||
connect(m_reader.get(), &BuildDirReader::errorOccured,
|
||||
this, &BuildDirManager::emitErrorOccured);
|
||||
connect(m_reader.get(), &BuildDirReader::dirty, this, &BuildDirManager::becameDirty);
|
||||
}
|
||||
QTC_ASSERT(m_reader, return);
|
||||
|
||||
m_reader->setParameters(p);
|
||||
|
||||
if (m_reader->isReady())
|
||||
@@ -125,27 +120,7 @@ void BuildDirManager::updateReaderType(std::function<void()> todo)
|
||||
connect(m_reader.get(), &BuildDirReader::isReadyNow, this, todo);
|
||||
}
|
||||
|
||||
void BuildDirManager::updateReaderData()
|
||||
{
|
||||
BuildDirReader::Parameters p(m_buildConfiguration);
|
||||
p.buildDirectory = workDirectory();
|
||||
|
||||
m_reader->setParameters(p);
|
||||
}
|
||||
|
||||
void BuildDirManager::parseOnceReaderReady(bool force, bool checkForChanges)
|
||||
{
|
||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
|
||||
m_buildTargets.clear();
|
||||
m_cmakeCache.clear();
|
||||
if (checkForChanges)
|
||||
checkConfiguration();
|
||||
m_reader->stop();
|
||||
m_reader->parse(force);
|
||||
}
|
||||
|
||||
void BuildDirManager::maybeForceReparseOnceReaderReady()
|
||||
bool BuildDirManager::hasConfigChanged()
|
||||
{
|
||||
checkConfiguration();
|
||||
|
||||
@@ -158,14 +133,13 @@ void BuildDirManager::maybeForceReparseOnceReaderReady()
|
||||
const QByteArrayList criticalKeys
|
||||
= {GENERATOR_KEY, CMAKE_COMMAND_KEY, CMAKE_C_COMPILER_KEY, CMAKE_CXX_COMPILER_KEY};
|
||||
|
||||
const CMakeConfig currentConfig = parsedConfiguration();
|
||||
const CMakeConfig currentConfig = takeCMakeConfiguration();
|
||||
|
||||
Kit *k = m_buildConfiguration->target()->kit();
|
||||
const CMakeTool *tool = CMakeKitInformation::cmakeTool(k);
|
||||
QTC_ASSERT(tool, return); // No cmake... we should not have ended up here in the first place
|
||||
const QString extraKitGenerator = CMakeGeneratorKitInformation::extraGenerator(k);
|
||||
const QString mainKitGenerator = CMakeGeneratorKitInformation::generator(k);
|
||||
CMakeConfig targetConfig = m_buildConfiguration->cmakeConfiguration();
|
||||
const CMakeTool *tool = m_parameters.cmakeTool;
|
||||
QTC_ASSERT(tool, return false); // No cmake... we should not have ended up here in the first place
|
||||
const QString extraKitGenerator = m_parameters.extraGenerator;
|
||||
const QString mainKitGenerator = m_parameters.generator;
|
||||
CMakeConfig targetConfig = m_parameters.configuration;
|
||||
targetConfig.append(CMakeConfigItem(GENERATOR_KEY, CMakeConfigItem::INTERNAL,
|
||||
QByteArray(), mainKitGenerator.toUtf8()));
|
||||
if (!extraKitGenerator.isEmpty())
|
||||
@@ -184,7 +158,7 @@ void BuildDirManager::maybeForceReparseOnceReaderReady()
|
||||
if (ccit->value != kcit->value) {
|
||||
if (criticalKeys.contains(kcit->key)) {
|
||||
clearCache();
|
||||
return;
|
||||
return false; // no need to trigger a new reader, clearCache will do that
|
||||
}
|
||||
mustReparse = true;
|
||||
}
|
||||
@@ -204,8 +178,7 @@ void BuildDirManager::maybeForceReparseOnceReaderReady()
|
||||
//
|
||||
// The critical keys *must* be set in cmake configuration, so those were already
|
||||
// handled above.
|
||||
if (mustReparse || kcit != targetConfig.constEnd())
|
||||
emit requestReparse(true);
|
||||
return mustReparse || kcit != targetConfig.constEnd();
|
||||
}
|
||||
|
||||
bool BuildDirManager::isParsing() const
|
||||
@@ -213,83 +186,96 @@ bool BuildDirManager::isParsing() const
|
||||
return m_reader && m_reader->isParsing();
|
||||
}
|
||||
|
||||
void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters ¶meters,
|
||||
int newReaderReparseOptions,
|
||||
int existingReaderReparseOptions)
|
||||
{
|
||||
QTC_ASSERT(parameters.isValid(), return);
|
||||
|
||||
if (m_reader)
|
||||
m_reader->stop();
|
||||
|
||||
BuildDirReader *old = m_reader.get();
|
||||
|
||||
m_parameters = parameters;
|
||||
m_parameters.buildDirectory = workDirectory(parameters);
|
||||
|
||||
updateReaderType(m_parameters,
|
||||
[this, old, newReaderReparseOptions, existingReaderReparseOptions]() {
|
||||
if (old != m_reader.get())
|
||||
emit requestReparse(newReaderReparseOptions);
|
||||
else
|
||||
emit requestReparse(existingReaderReparseOptions);
|
||||
});
|
||||
}
|
||||
|
||||
CMakeBuildConfiguration *BuildDirManager::buildConfiguration() const
|
||||
{
|
||||
return m_parameters.buildConfiguration;
|
||||
}
|
||||
|
||||
void BuildDirManager::becameDirty()
|
||||
{
|
||||
if (isParsing())
|
||||
return;
|
||||
|
||||
Target *t = m_buildConfiguration->target()->project()->activeTarget();
|
||||
BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr;
|
||||
|
||||
if (bc != m_buildConfiguration)
|
||||
if (!m_parameters.buildConfiguration || !m_parameters.buildConfiguration->isActive())
|
||||
return;
|
||||
|
||||
const CMakeTool *tool = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
|
||||
const CMakeTool *tool = m_parameters.cmakeTool;
|
||||
if (!tool->isAutoRun())
|
||||
return;
|
||||
|
||||
emit requestReparse(false);
|
||||
}
|
||||
|
||||
void BuildDirManager::forceReparse()
|
||||
{
|
||||
forceReparseImpl(true);
|
||||
}
|
||||
|
||||
void BuildDirManager::forceReparseWithoutCheckingForChanges()
|
||||
{
|
||||
forceReparseImpl(false);
|
||||
}
|
||||
|
||||
void BuildDirManager::forceReparseImpl(bool checkForChanges)
|
||||
{
|
||||
QTC_ASSERT(!m_isHandlingError, return);
|
||||
|
||||
if (m_buildConfiguration->target()->activeBuildConfiguration() != m_buildConfiguration)
|
||||
return;
|
||||
|
||||
CMakeTool *tool = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
|
||||
QTC_ASSERT(tool, return);
|
||||
|
||||
m_reader.reset(); // Force reparse by forcing in a new reader
|
||||
updateReaderType([this, checkForChanges]() { parseOnceReaderReady(true, checkForChanges); });
|
||||
emit requestReparse(REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
|
||||
void BuildDirManager::resetData()
|
||||
{
|
||||
QTC_ASSERT(!m_isHandlingError, return);
|
||||
|
||||
if (m_reader)
|
||||
m_reader->resetData();
|
||||
|
||||
m_cmakeCache.clear();
|
||||
m_reader.reset();
|
||||
|
||||
m_buildTargets.clear();
|
||||
}
|
||||
|
||||
bool BuildDirManager::persistCMakeState()
|
||||
{
|
||||
QTC_ASSERT(m_parameters.isValid(), return false);
|
||||
|
||||
if (!m_tempDir)
|
||||
return false;
|
||||
|
||||
const QString buildDir = m_buildConfiguration->buildDirectory().toString();
|
||||
QDir dir(buildDir);
|
||||
dir.mkpath(buildDir);
|
||||
const Utils::FileName buildDir = m_parameters.buildDirectory;
|
||||
QDir dir(buildDir.toString());
|
||||
dir.mkpath(buildDir.toString());
|
||||
|
||||
m_tempDir.reset(nullptr);
|
||||
|
||||
QTimer::singleShot(0, this, &BuildDirManager::parse); // make sure signals only happen afterwards!
|
||||
emit requestReparse(REPARSE_URGENT | REPARSE_FORCE_CONFIGURATION | REPARSE_CHECK_CONFIGURATION);
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuildDirManager::generateProjectTree(CMakeProjectNode *root, const QList<const FileNode *> &allFiles)
|
||||
void BuildDirManager::parse(int reparseParameters)
|
||||
{
|
||||
QTC_ASSERT(m_parameters.isValid(), return);
|
||||
QTC_ASSERT(m_reader, return);
|
||||
QTC_ASSERT((reparseParameters & REPARSE_FAIL) == 0, return);
|
||||
QTC_ASSERT((reparseParameters & REPARSE_IGNORE) == 0, return);
|
||||
|
||||
m_reader->stop();
|
||||
|
||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
|
||||
if (reparseParameters & REPARSE_CHECK_CONFIGURATION) {
|
||||
if (checkConfiguration())
|
||||
reparseParameters |= REPARSE_FORCE_CONFIGURATION;
|
||||
}
|
||||
|
||||
m_reader->parse(reparseParameters & REPARSE_FORCE_CONFIGURATION);
|
||||
}
|
||||
|
||||
void BuildDirManager::generateProjectTree(CMakeProjectNode *root, const QList<const FileNode *> &allFiles) const
|
||||
{
|
||||
QTC_ASSERT(!m_isHandlingError, return);
|
||||
QTC_ASSERT(m_reader, return);
|
||||
|
||||
const Utils::FileName projectFile = m_buildConfiguration->target()->project()->projectFilePath();
|
||||
|
||||
m_reader->generateProjectTree(root, allFiles);
|
||||
}
|
||||
|
||||
@@ -300,17 +286,13 @@ void BuildDirManager::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
return m_reader->updateCodeModel(rpps);
|
||||
}
|
||||
|
||||
void BuildDirManager::parse()
|
||||
{
|
||||
updateReaderType([this]() { parseOnceReaderReady(false); });
|
||||
}
|
||||
|
||||
void BuildDirManager::clearCache()
|
||||
{
|
||||
QTC_ASSERT(m_parameters.isValid(), return);
|
||||
QTC_ASSERT(!m_isHandlingError, return);
|
||||
|
||||
auto cmakeCache = Utils::FileName(workDirectory()).appendPath(QLatin1String("CMakeCache.txt"));
|
||||
auto cmakeFiles = Utils::FileName(workDirectory()).appendPath(QLatin1String("CMakeFiles"));
|
||||
auto cmakeCache = workDirectory(m_parameters).appendPath("CMakeCache.txt");
|
||||
auto cmakeFiles = workDirectory(m_parameters).appendPath("CMakeFiles");
|
||||
|
||||
const bool mustCleanUp = cmakeCache.exists() || cmakeFiles.exists();
|
||||
if (!mustCleanUp)
|
||||
@@ -319,7 +301,7 @@ void BuildDirManager::clearCache()
|
||||
Utils::FileUtils::removeRecursively(cmakeCache);
|
||||
Utils::FileUtils::removeRecursively(cmakeFiles);
|
||||
|
||||
forceReparse();
|
||||
m_reader.reset();
|
||||
}
|
||||
|
||||
static CMakeBuildTarget utilityTarget(const QString &title, const BuildDirManager *bdm)
|
||||
@@ -334,44 +316,41 @@ static CMakeBuildTarget utilityTarget(const QString &title, const BuildDirManage
|
||||
return target;
|
||||
}
|
||||
|
||||
QList<CMakeBuildTarget> BuildDirManager::buildTargets() const
|
||||
QList<CMakeBuildTarget> BuildDirManager::takeBuildTargets() const
|
||||
{
|
||||
QTC_ASSERT(!m_isHandlingError, return {});
|
||||
QList<CMakeBuildTarget> result = { utilityTarget(CMakeBuildStep::allTarget(), this),
|
||||
utilityTarget(CMakeBuildStep::cleanTarget(), this),
|
||||
utilityTarget(CMakeBuildStep::installTarget(), this),
|
||||
utilityTarget(CMakeBuildStep::testTarget(), this) };
|
||||
QTC_ASSERT(!m_isHandlingError, return result);
|
||||
|
||||
if (!m_reader)
|
||||
return QList<CMakeBuildTarget>();
|
||||
if (m_buildTargets.isEmpty()) {
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::allTarget(), this));
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::cleanTarget(), this));
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::installTarget(), this));
|
||||
m_buildTargets.append(utilityTarget(CMakeBuildStep::testTarget(), this));
|
||||
|
||||
m_buildTargets.append(Utils::filtered(m_reader->buildTargets(), [](const CMakeBuildTarget &bt) {
|
||||
if (m_reader) {
|
||||
result.append(Utils::filtered(m_reader->takeBuildTargets(), [](const CMakeBuildTarget &bt) {
|
||||
return bt.title != CMakeBuildStep::allTarget()
|
||||
&& bt.title != CMakeBuildStep::cleanTarget()
|
||||
&& bt.title != CMakeBuildStep::installTarget()
|
||||
&& bt.title != CMakeBuildStep::testTarget();
|
||||
}));
|
||||
}
|
||||
return m_buildTargets;
|
||||
return result;
|
||||
}
|
||||
|
||||
CMakeConfig BuildDirManager::parsedConfiguration() const
|
||||
CMakeConfig BuildDirManager::takeCMakeConfiguration() const
|
||||
{
|
||||
QTC_ASSERT(!m_isHandlingError, return {});
|
||||
|
||||
if (!m_reader)
|
||||
return m_cmakeCache;
|
||||
if (m_cmakeCache.isEmpty())
|
||||
m_cmakeCache = m_reader->takeParsedConfiguration();
|
||||
return CMakeConfig();
|
||||
|
||||
for (auto &ci : m_cmakeCache)
|
||||
CMakeConfig result = m_reader->takeParsedConfiguration();
|
||||
for (auto &ci : result)
|
||||
ci.inCMakeCache = true;
|
||||
|
||||
return m_cmakeCache;
|
||||
return result;
|
||||
}
|
||||
|
||||
CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile, QString *errorMessage)
|
||||
CMakeConfig BuildDirManager::parseCMakeConfiguration(const Utils::FileName &cacheFile,
|
||||
QString *errorMessage)
|
||||
{
|
||||
if (!cacheFile.exists()) {
|
||||
if (errorMessage)
|
||||
@@ -384,25 +363,26 @@ CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile
|
||||
return result;
|
||||
}
|
||||
|
||||
void BuildDirManager::checkConfiguration()
|
||||
bool BuildDirManager::checkConfiguration()
|
||||
{
|
||||
if (m_tempDir) // always throw away changes in the tmpdir!
|
||||
return;
|
||||
QTC_ASSERT(m_parameters.isValid(), return false);
|
||||
|
||||
Kit *k = m_buildConfiguration->target()->kit();
|
||||
const CMakeConfig cache = parsedConfiguration();
|
||||
if (m_tempDir) // always throw away changes in the tmpdir!
|
||||
return false;
|
||||
|
||||
const CMakeConfig cache = m_parameters.buildConfiguration->configurationFromCMake();
|
||||
if (cache.isEmpty())
|
||||
return; // No cache file yet.
|
||||
return false; // No cache file yet.
|
||||
|
||||
CMakeConfig newConfig;
|
||||
QSet<QString> changedKeys;
|
||||
QSet<QString> removedKeys;
|
||||
foreach (const CMakeConfigItem &iBc, m_buildConfiguration->cmakeConfiguration()) {
|
||||
foreach (const CMakeConfigItem &iBc, m_parameters.configuration) {
|
||||
const CMakeConfigItem &iCache
|
||||
= Utils::findOrDefault(cache, [&iBc](const CMakeConfigItem &i) { return i.key == iBc.key; });
|
||||
if (iCache.isNull()) {
|
||||
removedKeys << QString::fromUtf8(iBc.key);
|
||||
} else if (QString::fromUtf8(iCache.value) != iBc.expandedValue(k)) {
|
||||
} else if (QString::fromUtf8(iCache.value) != iBc.expandedValue(m_parameters.expander)) {
|
||||
changedKeys << QString::fromUtf8(iBc.key);
|
||||
newConfig.append(iCache);
|
||||
} else {
|
||||
@@ -435,22 +415,15 @@ void BuildDirManager::checkConfiguration()
|
||||
box->setDefaultButton(defaultButton);
|
||||
|
||||
box->exec();
|
||||
if (box->clickedButton() == applyButton)
|
||||
m_buildConfiguration->setCMakeConfiguration(newConfig);
|
||||
if (box->clickedButton() == applyButton) {
|
||||
m_parameters.configuration = newConfig;
|
||||
QSignalBlocker blocker(m_parameters.buildConfiguration);
|
||||
m_parameters.buildConfiguration->setConfigurationForCMake(newConfig);
|
||||
return false;
|
||||
} else if (box->clickedButton() == defaultButton)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void BuildDirManager::maybeForceReparse()
|
||||
{
|
||||
if (m_isHandlingError)
|
||||
return;
|
||||
|
||||
if (!m_reader || !m_reader->hasData()) {
|
||||
emit requestReparse(true);
|
||||
return;
|
||||
}
|
||||
|
||||
updateReaderType([this]() { maybeForceReparseOnceReaderReady(); });
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -25,9 +25,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builddirparameters.h"
|
||||
#include "builddirreader.h"
|
||||
#include "cmakebuildtarget.h"
|
||||
#include "cmakeconfigitem.h"
|
||||
|
||||
#include <cpptools/cpprawprojectpart.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/temporarydirectory.h>
|
||||
|
||||
@@ -37,12 +41,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
class FileNode;
|
||||
class IOutputParser;
|
||||
class Kit;
|
||||
class Task;
|
||||
} // namespace ProjectExplorer
|
||||
namespace ProjectExplorer { class FileNode; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
@@ -50,6 +49,7 @@ class CMakeTool;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class CMakeProjectNode;
|
||||
class CMakeBuildConfiguration;
|
||||
|
||||
class BuildDirManager : public QObject
|
||||
@@ -57,61 +57,63 @@ class BuildDirManager : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BuildDirManager(CMakeBuildConfiguration *bc);
|
||||
BuildDirManager();
|
||||
~BuildDirManager() final;
|
||||
|
||||
bool isParsing() const;
|
||||
|
||||
void setParametersAndRequestParse(const BuildDirParameters ¶meters,
|
||||
int newReaderReparseOptions, int existingReaderReparseOptions);
|
||||
CMakeBuildConfiguration *buildConfiguration() const;
|
||||
|
||||
void clearCache();
|
||||
void forceReparse();
|
||||
void forceReparseWithoutCheckingForChanges();
|
||||
void maybeForceReparse(); // Only reparse if the configuration has changed...
|
||||
|
||||
void resetData();
|
||||
bool persistCMakeState();
|
||||
|
||||
void parse(int reparseParameters);
|
||||
|
||||
void generateProjectTree(CMakeProjectNode *root,
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles) const;
|
||||
void updateCodeModel(CppTools::RawProjectParts &rpps);
|
||||
|
||||
QList<CMakeBuildTarget> buildTargets() const;
|
||||
CMakeConfig parsedConfiguration() const;
|
||||
QList<CMakeBuildTarget> takeBuildTargets() const;
|
||||
CMakeConfig takeCMakeConfiguration() const;
|
||||
|
||||
static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile,
|
||||
static CMakeConfig parseCMakeConfiguration(const Utils::FileName &cacheFile,
|
||||
QString *errorMessage);
|
||||
|
||||
CMakeBuildConfiguration *buildConfiguration() const { return m_buildConfiguration; }
|
||||
enum ReparseParameters { REPARSE_DEFAULT = 0, // use defaults
|
||||
REPARSE_URGENT = 1, // Do not wait for more requests, start ASAP
|
||||
REPARSE_FORCE_CONFIGURATION = 2, // Force configuration arguments to cmake
|
||||
REPARSE_CHECK_CONFIGURATION = 4, // Check and warn if on-disk config and QtC config differ
|
||||
REPARSE_IGNORE = 8, // Do not reparse:-)
|
||||
REPARSE_FAIL = 16 // Do not reparse and raise a warning
|
||||
};
|
||||
|
||||
signals:
|
||||
void requestReparse(bool urgent) const;
|
||||
void configurationStarted() const;
|
||||
void requestReparse(int reparseParameters) const;
|
||||
void parsingStarted() const;
|
||||
void dataAvailable() const;
|
||||
void errorOccured(const QString &err) const;
|
||||
|
||||
private:
|
||||
void emitDataAvailable();
|
||||
void emitErrorOccured(const QString &message) const;
|
||||
void checkConfiguration();
|
||||
bool checkConfiguration();
|
||||
|
||||
const Utils::FileName workDirectory() const;
|
||||
Utils::FileName workDirectory(const BuildDirParameters ¶meters) const;
|
||||
|
||||
void updateReaderType(std::function<void()> todo);
|
||||
void updateReaderData();
|
||||
void updateReaderType(const BuildDirParameters &p, std::function<void()> todo);
|
||||
|
||||
void forceReparseImpl(bool checkForChanges);
|
||||
void parseOnceReaderReady(bool force, bool checkForChanges = true);
|
||||
void maybeForceReparseOnceReaderReady();
|
||||
bool hasConfigChanged();
|
||||
|
||||
void parse();
|
||||
|
||||
void becameDirty();
|
||||
|
||||
CMakeBuildConfiguration *m_buildConfiguration = nullptr;
|
||||
BuildDirParameters m_parameters;
|
||||
mutable std::unique_ptr<Utils::TemporaryDirectory> m_tempDir = nullptr;
|
||||
mutable CMakeConfig m_cmakeCache;
|
||||
|
||||
std::unique_ptr<BuildDirReader> m_reader;
|
||||
|
||||
mutable QList<CMakeBuildTarget> m_buildTargets;
|
||||
mutable std::unique_ptr<BuildDirReader> m_reader;
|
||||
mutable bool m_isHandlingError = false;
|
||||
};
|
||||
|
||||
|
82
src/plugins/cmakeprojectmanager/builddirparameters.cpp
Normal file
82
src/plugins/cmakeprojectmanager/builddirparameters.cpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "builddirparameters.h"
|
||||
|
||||
#include "cmakebuildconfiguration.h"
|
||||
#include "cmakekitinformation.h"
|
||||
|
||||
#include <projectexplorer/kit.h>
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
BuildDirParameters::BuildDirParameters() = default;
|
||||
|
||||
BuildDirParameters::BuildDirParameters(CMakeBuildConfiguration *bc)
|
||||
{
|
||||
buildConfiguration = bc;
|
||||
|
||||
const Kit *k = bc->target()->kit();
|
||||
|
||||
projectName = bc->target()->project()->displayName();
|
||||
|
||||
sourceDirectory = bc->target()->project()->projectDirectory();
|
||||
buildDirectory = bc->buildDirectory();
|
||||
|
||||
environment = bc->environment();
|
||||
|
||||
cmakeTool = CMakeKitInformation::cmakeTool(k);
|
||||
|
||||
auto tc = ToolChainKitInformation::toolChain(k, Constants::CXX_LANGUAGE_ID);
|
||||
if (tc)
|
||||
cxxToolChainId = tc->id();
|
||||
tc = ToolChainKitInformation::toolChain(k, Constants::C_LANGUAGE_ID);
|
||||
if (tc)
|
||||
cToolChainId = tc->id();
|
||||
sysRoot = SysRootKitInformation::sysRoot(k);
|
||||
|
||||
expander = k->macroExpander();
|
||||
|
||||
configuration = bc->configurationForCMake();
|
||||
|
||||
generator = CMakeGeneratorKitInformation::generator(k);
|
||||
extraGenerator = CMakeGeneratorKitInformation::extraGenerator(k);
|
||||
platform = CMakeGeneratorKitInformation::platform(k);
|
||||
toolset = CMakeGeneratorKitInformation::toolset(k);
|
||||
generatorArguments = CMakeGeneratorKitInformation::generatorArguments(k);
|
||||
}
|
||||
|
||||
bool BuildDirParameters::isValid() const { return buildConfiguration && cmakeTool; }
|
||||
|
||||
BuildDirParameters::BuildDirParameters(const BuildDirParameters &) = default;
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CMakeProjectManager
|
75
src/plugins/cmakeprojectmanager/builddirparameters.h
Normal file
75
src/plugins/cmakeprojectmanager/builddirparameters.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cmakeconfigitem.h"
|
||||
#include "cmaketool.h"
|
||||
|
||||
#include <utils/environment.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/macroexpander.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class CMakeBuildConfiguration;
|
||||
|
||||
class BuildDirParameters {
|
||||
public:
|
||||
BuildDirParameters();
|
||||
BuildDirParameters(CMakeBuildConfiguration *bc);
|
||||
BuildDirParameters(const BuildDirParameters &other);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
CMakeBuildConfiguration *buildConfiguration = nullptr;
|
||||
QString projectName;
|
||||
|
||||
Utils::FileName sourceDirectory;
|
||||
Utils::FileName buildDirectory;
|
||||
Utils::Environment environment;
|
||||
CMakeTool *cmakeTool = nullptr;
|
||||
|
||||
QByteArray cxxToolChainId;
|
||||
QByteArray cToolChainId;
|
||||
|
||||
Utils::FileName sysRoot;
|
||||
|
||||
Utils::MacroExpander *expander = nullptr;
|
||||
|
||||
CMakeConfig configuration;
|
||||
|
||||
QString generator;
|
||||
QString extraGenerator;
|
||||
QString platform;
|
||||
QString toolset;
|
||||
QStringList generatorArguments;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace CMakeProjectManager
|
@@ -25,14 +25,10 @@
|
||||
|
||||
#include "builddirreader.h"
|
||||
|
||||
#include "cmakebuildconfiguration.h"
|
||||
#include "cmakekitinformation.h"
|
||||
#include "servermodereader.h"
|
||||
#include "tealeafreader.h"
|
||||
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@@ -43,57 +39,15 @@ namespace Internal {
|
||||
// BuildDirReader:
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
BuildDirReader::Parameters::Parameters() = default;
|
||||
|
||||
BuildDirReader::Parameters::Parameters(const CMakeBuildConfiguration *bc)
|
||||
BuildDirReader *BuildDirReader::createReader(const BuildDirParameters &p)
|
||||
{
|
||||
const ProjectExplorer::Kit *k = bc->target()->kit();
|
||||
|
||||
projectName = bc->target()->project()->displayName();
|
||||
|
||||
sourceDirectory = bc->target()->project()->projectDirectory();
|
||||
buildDirectory = bc->buildDirectory();
|
||||
|
||||
environment = bc->environment();
|
||||
|
||||
CMakeTool *cmake = CMakeKitInformation::cmakeTool(k);
|
||||
cmakeVersion = cmake->version();
|
||||
cmakeHasServerMode = cmake->hasServerMode();
|
||||
cmakeExecutable = cmake->cmakeExecutable();
|
||||
|
||||
pathMapper = cmake->pathMapper();
|
||||
isAutorun = cmake->isAutoRun();
|
||||
|
||||
auto tc = ProjectExplorer::ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||
if (tc)
|
||||
cxxToolChainId = tc->id();
|
||||
tc = ProjectExplorer::ToolChainKitInformation::toolChain(k, ProjectExplorer::Constants::C_LANGUAGE_ID);
|
||||
if (tc)
|
||||
cToolChainId = tc->id();
|
||||
sysRoot = ProjectExplorer::SysRootKitInformation::sysRoot(k);
|
||||
|
||||
expander = k->macroExpander();
|
||||
|
||||
configuration = bc->cmakeConfiguration();
|
||||
|
||||
generator = CMakeGeneratorKitInformation::generator(k);
|
||||
extraGenerator = CMakeGeneratorKitInformation::extraGenerator(k);
|
||||
platform = CMakeGeneratorKitInformation::platform(k);
|
||||
toolset = CMakeGeneratorKitInformation::toolset(k);
|
||||
generatorArguments = CMakeGeneratorKitInformation::generatorArguments(k);
|
||||
}
|
||||
|
||||
BuildDirReader::Parameters::Parameters(const BuildDirReader::Parameters &) = default;
|
||||
|
||||
|
||||
BuildDirReader *BuildDirReader::createReader(const BuildDirReader::Parameters &p)
|
||||
{
|
||||
if (p.cmakeHasServerMode)
|
||||
QTC_ASSERT(p.isValid() && p.cmakeTool, return nullptr);
|
||||
if (p.cmakeTool->hasServerMode())
|
||||
return new ServerModeReader;
|
||||
return new TeaLeafReader;
|
||||
}
|
||||
|
||||
void BuildDirReader::setParameters(const BuildDirReader::Parameters &p)
|
||||
void BuildDirReader::setParameters(const BuildDirParameters &p)
|
||||
{
|
||||
m_parameters = p;
|
||||
}
|
||||
|
@@ -25,8 +25,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "builddirparameters.h"
|
||||
#include "cmakebuildtarget.h"
|
||||
#include "cmakeconfigitem.h"
|
||||
#include "cmakeproject.h"
|
||||
#include "cmaketool.h"
|
||||
|
||||
#include <cpptools/cpprawprojectpart.h>
|
||||
@@ -38,6 +39,8 @@
|
||||
#include <QFutureInterface>
|
||||
#include <QObject>
|
||||
|
||||
namespace ProjectExplorer { class FileNode; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
@@ -49,52 +52,19 @@ class BuildDirReader : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Parameters {
|
||||
Parameters();
|
||||
Parameters(const CMakeBuildConfiguration *bc);
|
||||
Parameters(const Parameters &other);
|
||||
static BuildDirReader *createReader(const BuildDirParameters &p);
|
||||
virtual void setParameters(const BuildDirParameters &p);
|
||||
|
||||
QString projectName;
|
||||
|
||||
Utils::FileName sourceDirectory;
|
||||
Utils::FileName buildDirectory;
|
||||
Utils::Environment environment;
|
||||
Utils::FileName cmakeExecutable;
|
||||
CMakeTool::Version cmakeVersion;
|
||||
bool cmakeHasServerMode = false;
|
||||
CMakeTool::PathMapper pathMapper;
|
||||
|
||||
QByteArray cxxToolChainId;
|
||||
QByteArray cToolChainId;
|
||||
|
||||
Utils::FileName sysRoot;
|
||||
|
||||
Utils::MacroExpander *expander = nullptr;
|
||||
|
||||
CMakeConfig configuration;
|
||||
|
||||
QString generator;
|
||||
QString extraGenerator;
|
||||
QString platform;
|
||||
QString toolset;
|
||||
QStringList generatorArguments;
|
||||
bool isAutorun = false;
|
||||
};
|
||||
|
||||
static BuildDirReader *createReader(const BuildDirReader::Parameters &p);
|
||||
virtual void setParameters(const Parameters &p);
|
||||
|
||||
virtual bool isCompatible(const Parameters &p) = 0;
|
||||
virtual bool isCompatible(const BuildDirParameters &p) = 0;
|
||||
virtual void resetData() = 0;
|
||||
virtual void parse(bool force) = 0;
|
||||
virtual void parse(bool forceConfiguration) = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual bool isReady() const { return true; }
|
||||
virtual bool isParsing() const = 0;
|
||||
virtual bool hasData() const = 0;
|
||||
|
||||
virtual QList<CMakeBuildTarget> takeBuildTargets() = 0;
|
||||
virtual CMakeConfig takeParsedConfiguration() = 0;
|
||||
virtual QList<CMakeBuildTarget> buildTargets() const = 0;
|
||||
virtual void generateProjectTree(CMakeProjectNode *root,
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles) = 0;
|
||||
virtual void updateCodeModel(CppTools::RawProjectParts &rpps) = 0;
|
||||
@@ -107,7 +77,7 @@ signals:
|
||||
void errorOccured(const QString &message) const;
|
||||
|
||||
protected:
|
||||
Parameters m_parameters;
|
||||
BuildDirParameters m_parameters;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -64,17 +64,11 @@ const char INITIAL_ARGUMENTS[] = "CMakeProjectManager.CMakeBuildConfiguration.In
|
||||
const char CONFIGURATION_KEY[] = "CMake.Configuration";
|
||||
|
||||
CMakeBuildConfiguration::CMakeBuildConfiguration(ProjectExplorer::Target *parent) :
|
||||
BuildConfiguration(parent, Core::Id(Constants::CMAKE_BC_ID)),
|
||||
m_buildDirManager(new BuildDirManager(this))
|
||||
BuildConfiguration(parent, Core::Id(Constants::CMAKE_BC_ID))
|
||||
{
|
||||
ctor();
|
||||
}
|
||||
|
||||
CMakeBuildConfiguration::~CMakeBuildConfiguration()
|
||||
{
|
||||
m_buildDirManager->deleteLater(); // Do not block while waiting for cmake...
|
||||
}
|
||||
|
||||
bool CMakeBuildConfiguration::isEnabled() const
|
||||
{
|
||||
return m_error.isEmpty() && !isParsing();
|
||||
@@ -88,8 +82,7 @@ QString CMakeBuildConfiguration::disabledReason() const
|
||||
CMakeBuildConfiguration::CMakeBuildConfiguration(ProjectExplorer::Target *parent,
|
||||
CMakeBuildConfiguration *source) :
|
||||
BuildConfiguration(parent, source),
|
||||
m_configuration(source->m_configuration),
|
||||
m_buildDirManager(new BuildDirManager(this))
|
||||
m_configurationForCMake(source->m_configurationForCMake)
|
||||
{
|
||||
ctor();
|
||||
cloneSteps(source);
|
||||
@@ -99,7 +92,7 @@ QVariantMap CMakeBuildConfiguration::toMap() const
|
||||
{
|
||||
QVariantMap map(ProjectExplorer::BuildConfiguration::toMap());
|
||||
const QStringList config
|
||||
= Utils::transform(m_configuration, [](const CMakeConfigItem &i) { return i.toString(); });
|
||||
= Utils::transform(m_configurationForCMake, [](const CMakeConfigItem &i) { return i.toString(); });
|
||||
map.insert(QLatin1String(CONFIGURATION_KEY), config);
|
||||
return map;
|
||||
}
|
||||
@@ -130,110 +123,28 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
|
||||
}
|
||||
// End Legacy
|
||||
|
||||
setCMakeConfiguration(legacyConf + conf);
|
||||
setConfigurationForCMake(legacyConf + conf);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::ctor()
|
||||
{
|
||||
auto project = static_cast<CMakeProject *>(target()->project());
|
||||
setBuildDirectory(shadowBuildDirectory(project->projectFilePath(),
|
||||
auto p = static_cast<CMakeProject *>(project());
|
||||
setBuildDirectory(shadowBuildDirectory(p->projectFilePath(),
|
||||
target()->kit(),
|
||||
displayName(), BuildConfiguration::Unknown));
|
||||
|
||||
connect(m_buildDirManager.get(), &BuildDirManager::requestReparse,
|
||||
this, [this](bool urgent) { emit requestReparse(this, urgent); });
|
||||
connect(m_buildDirManager.get(), &BuildDirManager::dataAvailable,
|
||||
this, [this, project]() {
|
||||
clearError();
|
||||
project->handleParsingSuccess(this);
|
||||
});
|
||||
connect(m_buildDirManager.get(), &BuildDirManager::errorOccured,
|
||||
this, [this, project](const QString &msg) {
|
||||
setError(msg);
|
||||
project->handleParsingError(this);
|
||||
});
|
||||
connect(m_buildDirManager.get(), &BuildDirManager::configurationStarted,
|
||||
this, [this]() {
|
||||
clearError(ForceEnabledChanged::True);
|
||||
emit parsingStarted(this);
|
||||
});
|
||||
|
||||
connect(this, &CMakeBuildConfiguration::environmentChanged,
|
||||
m_buildDirManager.get(), &BuildDirManager::forceReparse);
|
||||
connect(this, &CMakeBuildConfiguration::buildDirectoryChanged,
|
||||
m_buildDirManager.get(), &BuildDirManager::forceReparse);
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::maybeForceReparse()
|
||||
{
|
||||
clearError();
|
||||
m_buildDirManager->maybeForceReparse();
|
||||
connect(p, &Project::parsingFinished, this, &BuildConfiguration::enabledChanged);
|
||||
}
|
||||
|
||||
bool CMakeBuildConfiguration::isParsing() const
|
||||
{
|
||||
return m_buildDirManager && m_buildDirManager->isParsing();
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::resetData()
|
||||
{
|
||||
clearError();
|
||||
m_buildDirManager->resetData();
|
||||
}
|
||||
|
||||
bool CMakeBuildConfiguration::persistCMakeState()
|
||||
{
|
||||
return m_buildDirManager->persistCMakeState();
|
||||
}
|
||||
|
||||
bool CMakeBuildConfiguration::updateCMakeStateBeforeBuild()
|
||||
{
|
||||
return static_cast<CMakeProject *>(project())->mustUpdateCMakeStateBeforeBuild();
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::runCMake()
|
||||
{
|
||||
if (!m_buildDirManager || m_buildDirManager->isParsing())
|
||||
return;
|
||||
|
||||
clearError();
|
||||
m_buildDirManager->forceReparse();
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::clearCache()
|
||||
{
|
||||
if (m_buildDirManager)
|
||||
m_buildDirManager->clearCache();
|
||||
return project()->isParsing() && isActive();
|
||||
}
|
||||
|
||||
QList<CMakeBuildTarget> CMakeBuildConfiguration::buildTargets() const
|
||||
{
|
||||
if (!m_buildDirManager || m_buildDirManager->isParsing())
|
||||
return QList<CMakeBuildTarget>();
|
||||
|
||||
return m_buildDirManager->buildTargets();
|
||||
}
|
||||
|
||||
CMakeProjectNode *
|
||||
CMakeBuildConfiguration::generateProjectTree(const QList<const FileNode*> &allFiles) const
|
||||
{
|
||||
if (!m_buildDirManager || m_buildDirManager->isParsing())
|
||||
return nullptr;
|
||||
|
||||
auto root = new CMakeProjectNode(target()->project()->projectDirectory());
|
||||
m_buildDirManager->generateProjectTree(root, allFiles);
|
||||
if (root->isEmpty()) {
|
||||
delete root;
|
||||
return nullptr;
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
{
|
||||
m_buildDirManager->updateCodeModel(rpps);
|
||||
return m_buildTargets;
|
||||
}
|
||||
|
||||
FileName CMakeBuildConfiguration::shadowBuildDirectory(const FileName &projectFilePath,
|
||||
@@ -273,50 +184,23 @@ void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
|
||||
cmBs->setBuildTarget(originalBuildTarget);
|
||||
}
|
||||
|
||||
QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration() const
|
||||
CMakeConfig CMakeBuildConfiguration::configurationFromCMake() const
|
||||
{
|
||||
if (!m_buildDirManager || m_buildDirManager->isParsing())
|
||||
return QList<ConfigModel::DataItem>();
|
||||
|
||||
return Utils::transform(m_buildDirManager->parsedConfiguration(),
|
||||
[](const CMakeConfigItem &i) {
|
||||
ConfigModel::DataItem j;
|
||||
j.key = QString::fromUtf8(i.key);
|
||||
j.value = QString::fromUtf8(i.value);
|
||||
j.description = QString::fromUtf8(i.documentation);
|
||||
j.values = i.values;
|
||||
j.inCMakeCache = i.inCMakeCache;
|
||||
|
||||
j.isAdvanced = i.isAdvanced;
|
||||
j.isHidden = i.type == CMakeConfigItem::INTERNAL || i.type == CMakeConfigItem::STATIC;
|
||||
|
||||
switch (i.type) {
|
||||
case CMakeConfigItem::FILEPATH:
|
||||
j.type = ConfigModel::DataItem::FILE;
|
||||
break;
|
||||
case CMakeConfigItem::PATH:
|
||||
j.type = ConfigModel::DataItem::DIRECTORY;
|
||||
break;
|
||||
case CMakeConfigItem::BOOL:
|
||||
j.type = ConfigModel::DataItem::BOOLEAN;
|
||||
break;
|
||||
case CMakeConfigItem::STRING:
|
||||
j.type = ConfigModel::DataItem::STRING;
|
||||
break;
|
||||
default:
|
||||
j.type = ConfigModel::DataItem::UNKNOWN;
|
||||
break;
|
||||
return m_configurationFromCMake;
|
||||
}
|
||||
|
||||
return j;
|
||||
});
|
||||
void CMakeBuildConfiguration::setConfigurationFromCMake(const CMakeConfig &config)
|
||||
{
|
||||
m_configurationFromCMake = config;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items)
|
||||
void CMakeBuildConfiguration::setBuildTargets(const QList<CMakeBuildTarget> &targets)
|
||||
{
|
||||
if (!m_buildDirManager || m_buildDirManager->isParsing())
|
||||
return;
|
||||
m_buildTargets = targets;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setConfigurationForCMake(const QList<ConfigModel::DataItem> &items)
|
||||
{
|
||||
const CMakeConfig newConfig = Utils::transform(items, [](const ConfigModel::DataItem &i) {
|
||||
CMakeConfigItem ni;
|
||||
ni.key = i.key.toUtf8();
|
||||
@@ -346,10 +230,8 @@ void CMakeBuildConfiguration::setCurrentCMakeConfiguration(const QList<ConfigMod
|
||||
return ni;
|
||||
});
|
||||
|
||||
const CMakeConfig config = cmakeConfiguration() + newConfig;
|
||||
setCMakeConfiguration(config);
|
||||
|
||||
m_buildDirManager->forceReparseWithoutCheckingForChanges();
|
||||
const CMakeConfig config = configurationForCMake() + newConfig;
|
||||
setConfigurationForCMake(config);
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::clearError(ForceEnabledChanged fec)
|
||||
@@ -383,14 +265,14 @@ static CMakeConfig removeDuplicates(const CMakeConfig &config)
|
||||
return result;
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setCMakeConfiguration(const CMakeConfig &config)
|
||||
void CMakeBuildConfiguration::setConfigurationForCMake(const CMakeConfig &config)
|
||||
{
|
||||
m_configuration = removeDuplicates(config);
|
||||
m_configurationForCMake = removeDuplicates(config);
|
||||
|
||||
const Kit *k = target()->kit();
|
||||
CMakeConfig kitConfig = CMakeConfigurationKitInformation::configuration(k);
|
||||
bool hasKitOverride = false;
|
||||
foreach (const CMakeConfigItem &i, m_configuration) {
|
||||
foreach (const CMakeConfigItem &i, m_configurationForCMake) {
|
||||
const QString b = CMakeConfigItem::expandedValueOf(k, i.key, kitConfig);
|
||||
if (!b.isNull() && i.expandedValue(k) != b) {
|
||||
hasKitOverride = true;
|
||||
@@ -402,11 +284,13 @@ void CMakeBuildConfiguration::setCMakeConfiguration(const CMakeConfig &config)
|
||||
setWarning(tr("CMake configuration set by the kit was overridden in the project."));
|
||||
else
|
||||
setWarning(QString());
|
||||
|
||||
emit configurationForCMakeChanged();
|
||||
}
|
||||
|
||||
CMakeConfig CMakeBuildConfiguration::cmakeConfiguration() const
|
||||
CMakeConfig CMakeBuildConfiguration::configurationForCMake() const
|
||||
{
|
||||
return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit()) + m_configuration);
|
||||
return removeDuplicates(CMakeConfigurationKitInformation::configuration(target()->kit()) + m_configurationForCMake);
|
||||
}
|
||||
|
||||
void CMakeBuildConfiguration::setError(const QString &message)
|
||||
@@ -556,7 +440,7 @@ ProjectExplorer::BuildConfiguration *CMakeBuildConfigurationFactory::create(Proj
|
||||
cleanSteps->insertStep(0, cleanStep);
|
||||
|
||||
bc->setBuildDirectory(copy.buildDirectory);
|
||||
bc->setCMakeConfiguration(copy.configuration);
|
||||
bc->setConfigurationForCMake(copy.configuration);
|
||||
|
||||
return bc;
|
||||
}
|
||||
|
@@ -52,11 +52,9 @@ class CMakeProjectNode;
|
||||
class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class CMakeBuildConfigurationFactory;
|
||||
|
||||
public:
|
||||
CMakeBuildConfiguration(ProjectExplorer::Target *parent);
|
||||
~CMakeBuildConfiguration();
|
||||
|
||||
bool isEnabled() const override;
|
||||
QString disabledReason() const override;
|
||||
@@ -69,25 +67,13 @@ public:
|
||||
|
||||
void emitBuildTypeChanged();
|
||||
|
||||
void setCMakeConfiguration(const CMakeConfig &config);
|
||||
bool hasCMakeConfiguration() const;
|
||||
CMakeConfig cmakeConfiguration() const;
|
||||
CMakeConfig configurationForCMake() const;
|
||||
CMakeConfig configurationFromCMake() const;
|
||||
|
||||
QString error() const;
|
||||
QString warning() const;
|
||||
|
||||
bool isParsing() const;
|
||||
|
||||
void maybeForceReparse();
|
||||
void resetData();
|
||||
bool persistCMakeState();
|
||||
bool updateCMakeStateBeforeBuild();
|
||||
void runCMake();
|
||||
void clearCache();
|
||||
|
||||
QList<CMakeBuildTarget> buildTargets() const;
|
||||
CMakeProjectManager::Internal::CMakeProjectNode *generateProjectTree(const QList<const ProjectExplorer::FileNode *> &allFiles) const;
|
||||
void updateCodeModel(CppTools::RawProjectParts &rpps);
|
||||
|
||||
static Utils::FileName
|
||||
shadowBuildDirectory(const Utils::FileName &projectFilePath, const ProjectExplorer::Kit *k,
|
||||
@@ -97,12 +83,11 @@ public:
|
||||
void buildTarget(const QString &buildTarget);
|
||||
|
||||
signals:
|
||||
void requestReparse(CMakeBuildConfiguration *, bool isUrgent);
|
||||
void parsingStarted(CMakeBuildConfiguration *);
|
||||
|
||||
void errorOccured(const QString &message);
|
||||
void warningOccured(const QString &message);
|
||||
|
||||
void configurationForCMakeChanged();
|
||||
|
||||
protected:
|
||||
CMakeBuildConfiguration(ProjectExplorer::Target *parent, CMakeBuildConfiguration *source);
|
||||
bool fromMap(const QVariantMap &map) override;
|
||||
@@ -110,22 +95,30 @@ protected:
|
||||
private:
|
||||
void ctor();
|
||||
|
||||
bool isParsing() const;
|
||||
|
||||
enum ForceEnabledChanged : quint8 { False, True };
|
||||
void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
|
||||
QList<ConfigModel::DataItem> completeCMakeConfiguration() const;
|
||||
void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items);
|
||||
|
||||
void setBuildTargets(const QList<CMakeBuildTarget> &targets);
|
||||
void setConfigurationFromCMake(const CMakeConfig &config);
|
||||
void setConfigurationForCMake(const QList<ConfigModel::DataItem> &items);
|
||||
void setConfigurationForCMake(const CMakeConfig &config);
|
||||
|
||||
void setError(const QString &message);
|
||||
void setWarning(const QString &message);
|
||||
|
||||
CMakeConfig m_configuration;
|
||||
CMakeConfig m_configurationForCMake;
|
||||
QString m_error;
|
||||
QString m_warning;
|
||||
|
||||
std::unique_ptr<BuildDirManager> m_buildDirManager;
|
||||
CMakeConfig m_configurationFromCMake;
|
||||
QList<CMakeBuildTarget> m_buildTargets;
|
||||
|
||||
friend class CMakeBuildConfigurationFactory;
|
||||
friend class CMakeBuildSettingsWidget;
|
||||
friend class CMakeProjectManager::CMakeProject;
|
||||
friend class BuildDirManager;
|
||||
};
|
||||
|
||||
class CMakeProjectImporter;
|
||||
|
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
QTC_ASSERT(bc->target()->project(), return);
|
||||
sourceDirectory = bc->target()->project()->projectDirectory().toString();
|
||||
configuration = bc->cmakeConfiguration();
|
||||
configuration = bc->configurationForCMake();
|
||||
}
|
||||
|
||||
bool operator==(const BuildInfo &o) const final
|
||||
|
@@ -227,13 +227,13 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
if (m_buildConfiguration->isParsing())
|
||||
m_showProgressTimer.start();
|
||||
else {
|
||||
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
|
||||
m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
|
||||
m_configView->expandAll();
|
||||
}
|
||||
|
||||
connect(m_buildConfiguration->target()->project(), &ProjectExplorer::Project::parsingFinished,
|
||||
connect(project, &ProjectExplorer::Project::parsingFinished,
|
||||
this, [this, buildDirChooser, stretcher]() {
|
||||
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
|
||||
m_configModel->setConfiguration(m_buildConfiguration->configurationFromCMake());
|
||||
m_configView->expandAll();
|
||||
stretcher->stretch();
|
||||
updateButtonState();
|
||||
@@ -264,7 +264,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
|
||||
|
||||
connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges);
|
||||
connect(m_reconfigureButton, &QPushButton::clicked, this, [this]() {
|
||||
m_buildConfiguration->setCurrentCMakeConfiguration(m_configModel->configurationChanges());
|
||||
m_buildConfiguration->setConfigurationForCMake(m_configModel->configurationChanges());
|
||||
});
|
||||
connect(m_editButton, &QPushButton::clicked, this, [this]() {
|
||||
QModelIndex idx = m_configView->currentIndex();
|
||||
|
@@ -269,10 +269,11 @@ void CMakeBuildStep::run(QFutureInterface<bool> &fi)
|
||||
QTC_ASSERT(bc, return);
|
||||
|
||||
bool mustDelay = false;
|
||||
if (bc->persistCMakeState()) {
|
||||
auto p = static_cast<CMakeProject *>(bc->project());
|
||||
if (p->persistCMakeState()) {
|
||||
emit addOutput(tr("Persisting CMake state..."), BuildStep::OutputFormat::NormalMessage);
|
||||
mustDelay = true;
|
||||
} else if (bc->updateCMakeStateBeforeBuild()) {
|
||||
} else if (p->mustUpdateCMakeStateBeforeBuild()) {
|
||||
emit addOutput(tr("Running CMake in preparation to build..."), BuildStep::OutputFormat::NormalMessage);
|
||||
mustDelay = true;
|
||||
} else {
|
||||
|
46
src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp
Normal file
46
src/plugins/cmakeprojectmanager/cmakebuildtarget.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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 "cmakebuildtarget.h"
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
void CMakeBuildTarget::clear()
|
||||
{
|
||||
executable.clear();
|
||||
makeCommand.clear();
|
||||
workingDirectory.clear();
|
||||
sourceDirectory.clear();
|
||||
title.clear();
|
||||
targetType = UtilityType;
|
||||
includeFiles.clear();
|
||||
compilerOptions.clear();
|
||||
macros.clear();
|
||||
files.clear();
|
||||
}
|
||||
|
||||
} // namespace CMakeProjectManager
|
64
src/plugins/cmakeprojectmanager/cmakebuildtarget.h
Normal file
64
src/plugins/cmakeprojectmanager/cmakebuildtarget.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 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.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cmake_global.h"
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
enum TargetType {
|
||||
ExecutableType = 0,
|
||||
StaticLibraryType = 2,
|
||||
DynamicLibraryType = 3,
|
||||
UtilityType = 64
|
||||
};
|
||||
|
||||
class CMAKE_EXPORT CMakeBuildTarget
|
||||
{
|
||||
public:
|
||||
QString title;
|
||||
Utils::FileName executable; // TODO: rename to output?
|
||||
TargetType targetType = UtilityType;
|
||||
Utils::FileName workingDirectory;
|
||||
Utils::FileName sourceDirectory;
|
||||
Utils::FileName makeCommand;
|
||||
|
||||
// code model
|
||||
QList<Utils::FileName> includeFiles;
|
||||
QStringList compilerOptions;
|
||||
ProjectExplorer::Macros macros;
|
||||
QList<Utils::FileName> files;
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
} // namespace CMakeProjectManager
|
@@ -42,6 +42,7 @@
|
||||
#include <projectexplorer/deploymentdata.h>
|
||||
#include <projectexplorer/headerpath.h>
|
||||
#include <projectexplorer/kitinformation.h>
|
||||
#include <projectexplorer/kitmanager.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <projectexplorer/toolchain.h>
|
||||
@@ -66,6 +67,11 @@ namespace CMakeProjectManager {
|
||||
|
||||
using namespace Internal;
|
||||
|
||||
static CMakeBuildConfiguration *activeBc(const CMakeProject *p)
|
||||
{
|
||||
return qobject_cast<CMakeBuildConfiguration *>(p->activeTarget() ? p->activeTarget()->activeBuildConfiguration() : nullptr);
|
||||
}
|
||||
|
||||
// QtCreator CMake Generator wishlist:
|
||||
// Which make targets we need to build to get all executables
|
||||
// What is the actual compiler executable
|
||||
@@ -77,27 +83,129 @@ using namespace Internal;
|
||||
CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEMIMETYPE, fileName),
|
||||
m_cppCodeModelUpdater(new CppTools::CppProjectUpdater(this))
|
||||
{
|
||||
m_delayedParsingTimer.setSingleShot(true);
|
||||
|
||||
connect(&m_delayedParsingTimer, &QTimer::timeout,
|
||||
this, [this]() { startParsingProject(PARSE); });
|
||||
|
||||
setId(CMakeProjectManager::Constants::CMAKEPROJECT_ID);
|
||||
|
||||
setProjectContext(Core::Context(CMakeProjectManager::Constants::PROJECTCONTEXT));
|
||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||
setDisplayName(projectDirectory().fileName());
|
||||
|
||||
connect(this, &Project::activeProjectConfigurationChanged,
|
||||
this, &CMakeProject::handleActiveProjectConfigurationChanged);
|
||||
// Timer:
|
||||
m_delayedParsingTimer.setSingleShot(true);
|
||||
|
||||
subscribeSignal(&CMakeBuildConfiguration::requestReparse,
|
||||
this, [this](CMakeBuildConfiguration *bc, bool isUrgent) {
|
||||
if (bc->isActive()) {
|
||||
m_delayedParsingTimer.setInterval(isUrgent ? 0 : 1000);
|
||||
m_delayedParsingTimer.start();
|
||||
connect(&m_delayedParsingTimer, &QTimer::timeout,
|
||||
this, [this]() { startParsing(m_delayedParsingParameters); });
|
||||
|
||||
// BuildDirManager:
|
||||
connect(&m_buildDirManager, &BuildDirManager::requestReparse,
|
||||
this, &CMakeProject::handleReparseRequest);
|
||||
connect(&m_buildDirManager, &BuildDirManager::dataAvailable,
|
||||
this, [this]() {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc && bc == m_buildDirManager.buildConfiguration()) {
|
||||
bc->clearError();
|
||||
handleParsingSuccess(bc);
|
||||
}
|
||||
});
|
||||
connect(&m_buildDirManager, &BuildDirManager::errorOccured,
|
||||
this, [this](const QString &msg) {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc && bc == m_buildDirManager.buildConfiguration()) {
|
||||
bc->setError(msg);
|
||||
handleParsingError(bc);
|
||||
}
|
||||
});
|
||||
connect(&m_buildDirManager, &BuildDirManager::parsingStarted,
|
||||
this, [this]() {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc && bc == m_buildDirManager.buildConfiguration())
|
||||
bc->clearError(CMakeBuildConfiguration::ForceEnabledChanged::True);
|
||||
});
|
||||
|
||||
// Kit changed:
|
||||
connect(KitManager::instance(), &KitManager::kitUpdated,
|
||||
this, [this](Kit *k) {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (!bc || k != bc->target()->kit())
|
||||
return; // not for us...
|
||||
|
||||
// Build configuration has not changed, but Kit settings might have:
|
||||
// reparse and check the configuration, independent of whether the reader has changed
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(bc),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
});
|
||||
|
||||
// Target switched:
|
||||
connect(this, &Project::activeTargetChanged, this, [this]() {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
|
||||
// Target has switched, so the kit has changed, too.
|
||||
// * run cmake with configuration arguments if the reader needs to be switched
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(bc),
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
});
|
||||
|
||||
// BuildConfiguration switched:
|
||||
subscribeSignal(&Target::activeBuildConfigurationChanged, this, [this]() {
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
|
||||
// Build configuration has switched:
|
||||
// * Error out if the reader updates, can not happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(bc),
|
||||
BuildDirManager::REPARSE_FAIL,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
});
|
||||
|
||||
// BuildConfiguration changed:
|
||||
subscribeSignal(&CMakeBuildConfiguration::environmentChanged, this, [this]() {
|
||||
auto senderBc = qobject_cast<CMakeBuildConfiguration *>(sender());
|
||||
|
||||
if (senderBc && senderBc->isActive()) {
|
||||
// The environment on our BC has changed:
|
||||
// * Error out if the reader updates, can not happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(senderBc),
|
||||
BuildDirManager::REPARSE_FAIL,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
subscribeSignal(&CMakeBuildConfiguration::buildDirectoryChanged, this, [this]() {
|
||||
auto senderBc = qobject_cast<CMakeBuildConfiguration *>(sender());
|
||||
|
||||
if (senderBc && senderBc->isActive() && senderBc == m_buildDirManager.buildConfiguration()) {
|
||||
// The build directory of our BC has changed:
|
||||
// * Error out if the reader updates, can not happen since all BCs share a target/kit.
|
||||
// * run cmake without configuration arguments if the reader stays
|
||||
// If no configuration exists, then the arguments will get added automatically by
|
||||
// the reader.
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(senderBc),
|
||||
BuildDirManager::REPARSE_FAIL,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
subscribeSignal(&CMakeBuildConfiguration::configurationForCMakeChanged, this, [this]() {
|
||||
auto senderBc = qobject_cast<CMakeBuildConfiguration *>(sender());
|
||||
|
||||
if (senderBc && senderBc->isActive() && senderBc == m_buildDirManager.buildConfiguration()) {
|
||||
// The CMake configuration has changed on our BC:
|
||||
// * Error out if the reader updates, can not happen since all BCs share a target/kit.
|
||||
// * run cmake with configuration arguments if the reader stays
|
||||
m_buildDirManager.setParametersAndRequestParse(
|
||||
BuildDirParameters(senderBc),
|
||||
BuildDirManager::REPARSE_FAIL,
|
||||
BuildDirManager::REPARSE_FORCE_CONFIGURATION);
|
||||
}
|
||||
});
|
||||
|
||||
// TreeScanner:
|
||||
connect(&m_treeScanner, &TreeScanner::finished, this, &CMakeProject::handleTreeScanningFinished);
|
||||
|
||||
m_treeScanner.setFilter([this](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
|
||||
@@ -148,15 +256,19 @@ CMakeProject::~CMakeProject()
|
||||
|
||||
void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
|
||||
{
|
||||
Target *const t = activeTarget();
|
||||
const CMakeBuildConfiguration *aBc = activeBc(this);
|
||||
|
||||
QTC_ASSERT(bc, return);
|
||||
QTC_ASSERT(bc == (t ? t->activeBuildConfiguration() : nullptr), return);
|
||||
QTC_ASSERT(m_treeScanner.isFinished() && !bc->isParsing(), return);
|
||||
QTC_ASSERT(bc == aBc, return);
|
||||
QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return);
|
||||
|
||||
Target *t = bc->target();
|
||||
Kit *k = t->kit();
|
||||
|
||||
auto newRoot = bc->generateProjectTree(m_allFiles);
|
||||
bc->setBuildTargets(m_buildDirManager.takeBuildTargets());
|
||||
bc->setConfigurationFromCMake(m_buildDirManager.takeCMakeConfiguration());
|
||||
|
||||
auto newRoot = generateProjectTree(m_allFiles);
|
||||
if (newRoot) {
|
||||
setDisplayName(newRoot->displayName());
|
||||
setRootProjectNode(newRoot);
|
||||
@@ -184,7 +296,7 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
|
||||
}
|
||||
|
||||
CppTools::RawProjectParts rpps;
|
||||
bc->updateCodeModel(rpps);
|
||||
m_buildDirManager.updateCodeModel(rpps);
|
||||
|
||||
for (CppTools::RawProjectPart &rpp : rpps) {
|
||||
// TODO: Set the Qt version only if target actually depends on Qt.
|
||||
@@ -197,6 +309,8 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
|
||||
|
||||
updateQmlJSCodeModel();
|
||||
|
||||
m_buildDirManager.resetData();
|
||||
|
||||
emit fileListChanged();
|
||||
|
||||
emit bc->emitBuildTypeChanged();
|
||||
@@ -220,10 +334,10 @@ void CMakeProject::updateQmlJSCodeModel()
|
||||
if (!bc)
|
||||
return;
|
||||
|
||||
const QList<ConfigModel::DataItem> &cm = bc->completeCMakeConfiguration();
|
||||
foreach (const ConfigModel::DataItem &di, cm) {
|
||||
if (di.key.contains(QStringLiteral("QML_IMPORT_PATH"))) {
|
||||
cmakeImports = di.value;
|
||||
const CMakeConfig &cm = bc->configurationFromCMake();
|
||||
foreach (const CMakeConfigItem &di, cm) {
|
||||
if (di.key.contains("QML_IMPORT_PATH")) {
|
||||
cmakeImports = QString::fromUtf8(di.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -234,6 +348,16 @@ void CMakeProject::updateQmlJSCodeModel()
|
||||
modelManager->updateProjectInfo(projectInfo, this);
|
||||
}
|
||||
|
||||
CMakeProjectNode *CMakeProject::generateProjectTree(const QList<const FileNode *> &allFiles) const
|
||||
{
|
||||
if (m_buildDirManager.isParsing())
|
||||
return nullptr;
|
||||
|
||||
auto root = std::make_unique<CMakeProjectNode>(projectDirectory());
|
||||
m_buildDirManager.generateProjectTree(root.get(), allFiles);
|
||||
return root ? root.release() : nullptr;
|
||||
}
|
||||
|
||||
bool CMakeProject::needsConfiguration() const
|
||||
{
|
||||
return targets().isEmpty();
|
||||
@@ -264,53 +388,28 @@ void CMakeProject::runCMake()
|
||||
if (isParsing())
|
||||
return;
|
||||
|
||||
startParsingProject(PARSE);
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc) {
|
||||
BuildDirParameters parameters(bc);
|
||||
m_buildDirManager.setParametersAndRequestParse(parameters,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION,
|
||||
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProject::runCMakeAndScanProjectTree()
|
||||
{
|
||||
if (isParsing())
|
||||
if (!m_treeScanner.isFinished())
|
||||
return;
|
||||
|
||||
startParsingProject(static_cast<DataCollectionAction>(PARSE | SCAN));
|
||||
}
|
||||
|
||||
void CMakeProject::startParsingProject(const CMakeProject::DataCollectionAction action)
|
||||
{
|
||||
const bool runParse = action & PARSE;
|
||||
const bool runScan = action & SCAN;
|
||||
|
||||
CMakeBuildConfiguration *bc = activeTarget()
|
||||
? qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration())
|
||||
: nullptr;
|
||||
if (!bc)
|
||||
return;
|
||||
|
||||
if (!m_treeScanner.isFinished() || m_waitingForScan)
|
||||
return;
|
||||
|
||||
emitParsingStarted();
|
||||
|
||||
m_waitingForParse = runParse;
|
||||
m_waitingForScan = runScan;
|
||||
m_combinedScanAndParseResult = true;
|
||||
|
||||
if (runParse)
|
||||
bc->runCMake();
|
||||
|
||||
if (runScan) {
|
||||
m_treeScanner.asyncScanForFiles(projectDirectory());
|
||||
Core::ProgressManager::addTask(m_treeScanner.future(),
|
||||
tr("Scan \"%1\" project tree").arg(displayName()),
|
||||
"CMake.Scan.Tree");
|
||||
}
|
||||
m_waitingForScan = true;
|
||||
runCMake();
|
||||
}
|
||||
|
||||
void CMakeProject::buildCMakeTarget(const QString &buildTarget)
|
||||
{
|
||||
QTC_ASSERT(!buildTarget.isEmpty(), return);
|
||||
Target *t = activeTarget();
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(t ? t->activeBuildConfiguration() : nullptr);
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
if (bc)
|
||||
bc->buildTarget(buildTarget);
|
||||
}
|
||||
@@ -322,15 +421,60 @@ ProjectImporter *CMakeProject::projectImporter() const
|
||||
return m_projectImporter.get();
|
||||
}
|
||||
|
||||
bool CMakeProject::persistCMakeState()
|
||||
{
|
||||
return m_buildDirManager.persistCMakeState();
|
||||
}
|
||||
|
||||
void CMakeProject::clearCMakeCache()
|
||||
{
|
||||
m_buildDirManager.clearCache();
|
||||
}
|
||||
|
||||
QList<CMakeBuildTarget> CMakeProject::buildTargets() const
|
||||
{
|
||||
CMakeBuildConfiguration *bc = nullptr;
|
||||
if (activeTarget())
|
||||
bc = qobject_cast<CMakeBuildConfiguration *>(activeTarget()->activeBuildConfiguration());
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
|
||||
return bc ? bc->buildTargets() : QList<CMakeBuildTarget>();
|
||||
}
|
||||
|
||||
void CMakeProject::handleReparseRequest(int reparseParameters)
|
||||
{
|
||||
QTC_ASSERT(!(reparseParameters & BuildDirManager::REPARSE_FAIL), return);
|
||||
if (reparseParameters & BuildDirManager::REPARSE_IGNORE)
|
||||
return;
|
||||
|
||||
m_delayedParsingTimer.setInterval((reparseParameters & BuildDirManager::REPARSE_URGENT) ? 0 : 1000);
|
||||
m_delayedParsingTimer.start();
|
||||
m_delayedParsingParameters = m_delayedParsingParameters | reparseParameters;
|
||||
}
|
||||
|
||||
void CMakeProject::startParsing(int reparseParameters)
|
||||
{
|
||||
m_delayedParsingParameters = BuildDirManager::REPARSE_DEFAULT;
|
||||
|
||||
QTC_ASSERT((reparseParameters & BuildDirManager::REPARSE_FAIL) == 0, return);
|
||||
if (reparseParameters & BuildDirManager::REPARSE_IGNORE)
|
||||
return;
|
||||
|
||||
QTC_ASSERT(activeBc(this), return);
|
||||
|
||||
emitParsingStarted();
|
||||
|
||||
m_waitingForParse = true;
|
||||
m_combinedScanAndParseResult = true;
|
||||
|
||||
if (m_waitingForScan) {
|
||||
QTC_CHECK(m_treeScanner.isFinished());
|
||||
m_treeScanner.asyncScanForFiles(projectDirectory());
|
||||
Core::ProgressManager::addTask(m_treeScanner.future(),
|
||||
tr("Scan \"%1\" project tree").arg(displayName()),
|
||||
"CMake.Scan.Tree");
|
||||
}
|
||||
|
||||
m_buildDirManager.parse(reparseParameters);
|
||||
}
|
||||
|
||||
QStringList CMakeProject::buildTargetTitles(bool runnable) const
|
||||
{
|
||||
const QList<CMakeBuildTarget> targets
|
||||
@@ -361,33 +505,9 @@ bool CMakeProject::setupTarget(Target *t)
|
||||
if (t->buildConfigurations().isEmpty())
|
||||
return false;
|
||||
t->updateDefaultDeployConfigurations();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMakeProject::handleActiveProjectConfigurationChanged(ProjectConfiguration *pc)
|
||||
{
|
||||
if (auto bc = qobject_cast<CMakeBuildConfiguration *>(pc)) {
|
||||
if (!bc->isActive())
|
||||
return;
|
||||
} else if (!qobject_cast<Target *>(pc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Target *t : targets()) {
|
||||
for (BuildConfiguration *bc : t->buildConfigurations()) {
|
||||
auto i = qobject_cast<CMakeBuildConfiguration *>(bc);
|
||||
QTC_ASSERT(i, continue);
|
||||
if (i->isActive()) {
|
||||
m_waitingForParse = true;
|
||||
i->maybeForceReparse();
|
||||
} else {
|
||||
i->resetData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProject::handleTreeScanningFinished()
|
||||
{
|
||||
QTC_CHECK(m_waitingForScan);
|
||||
@@ -395,8 +515,7 @@ void CMakeProject::handleTreeScanningFinished()
|
||||
qDeleteAll(m_allFiles);
|
||||
m_allFiles = Utils::transform(m_treeScanner.release(), [](const FileNode *fn) { return fn; });
|
||||
|
||||
auto t = activeTarget();
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration*>(t ? t->activeBuildConfiguration() : nullptr);
|
||||
CMakeBuildConfiguration *bc = activeBc(this);
|
||||
QTC_ASSERT(bc, return);
|
||||
|
||||
m_combinedScanAndParseResult = m_combinedScanAndParseResult && true;
|
||||
@@ -407,7 +526,7 @@ void CMakeProject::handleTreeScanningFinished()
|
||||
|
||||
void CMakeProject::handleParsingSuccess(CMakeBuildConfiguration *bc)
|
||||
{
|
||||
QTC_CHECK(m_waitingForParse);
|
||||
QTC_ASSERT(m_waitingForParse, return);
|
||||
|
||||
if (!bc || !bc->isActive())
|
||||
return;
|
||||
@@ -626,18 +745,4 @@ void CMakeProject::createGeneratedCodeModelSupport()
|
||||
CppTools::GeneratedCodeModelSupport::update(m_extraCompilers);
|
||||
}
|
||||
|
||||
void CMakeBuildTarget::clear()
|
||||
{
|
||||
executable.clear();
|
||||
makeCommand.clear();
|
||||
workingDirectory.clear();
|
||||
sourceDirectory.clear();
|
||||
title.clear();
|
||||
targetType = UtilityType;
|
||||
includeFiles.clear();
|
||||
compilerOptions.clear();
|
||||
macros.clear();
|
||||
files.clear();
|
||||
}
|
||||
|
||||
} // namespace CMakeProjectManager
|
||||
|
@@ -26,8 +26,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "cmake_global.h"
|
||||
#include "builddirmanager.h"
|
||||
#include "cmakebuildtarget.h"
|
||||
#include "cmakeprojectimporter.h"
|
||||
#include "treescanner.h"
|
||||
#include "builddirmanager.h"
|
||||
|
||||
#include <projectexplorer/extracompiler.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
@@ -42,40 +45,16 @@
|
||||
#include <memory>
|
||||
|
||||
namespace CppTools { class CppProjectUpdater; }
|
||||
namespace ProjectExplorer { class FileNode; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
|
||||
namespace Internal {
|
||||
class CMakeBuildConfiguration;
|
||||
class CMakeBuildSettingsWidget;
|
||||
class CMakeProjectNode;
|
||||
} // namespace Internal
|
||||
|
||||
enum TargetType {
|
||||
ExecutableType = 0,
|
||||
StaticLibraryType = 2,
|
||||
DynamicLibraryType = 3,
|
||||
UtilityType = 64
|
||||
};
|
||||
|
||||
class CMAKE_EXPORT CMakeBuildTarget
|
||||
{
|
||||
public:
|
||||
QString title;
|
||||
Utils::FileName executable; // TODO: rename to output?
|
||||
TargetType targetType = UtilityType;
|
||||
Utils::FileName workingDirectory;
|
||||
Utils::FileName sourceDirectory;
|
||||
Utils::FileName makeCommand;
|
||||
|
||||
// code model
|
||||
QList<Utils::FileName> includeFiles;
|
||||
QStringList compilerOptions;
|
||||
ProjectExplorer::Macros macros;
|
||||
QList<Utils::FileName> files;
|
||||
|
||||
void clear();
|
||||
};
|
||||
|
||||
class CMAKE_EXPORT CMakeProject : public ProjectExplorer::Project
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -103,6 +82,10 @@ public:
|
||||
|
||||
ProjectExplorer::ProjectImporter *projectImporter() const final;
|
||||
|
||||
bool persistCMakeState();
|
||||
void clearCMakeCache();
|
||||
bool mustUpdateCMakeStateBeforeBuild();
|
||||
|
||||
protected:
|
||||
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) final;
|
||||
bool setupTarget(ProjectExplorer::Target *t) final;
|
||||
@@ -110,10 +93,10 @@ protected:
|
||||
private:
|
||||
QList<CMakeBuildTarget> buildTargets() const;
|
||||
|
||||
enum DataCollectionAction { PARSE = 1, SCAN = 2 };
|
||||
void startParsingProject(const DataCollectionAction a);
|
||||
void handleReparseRequest(int reparseParameters);
|
||||
|
||||
void startParsing(int reparseParameters);
|
||||
|
||||
void handleActiveProjectConfigurationChanged(ProjectExplorer::ProjectConfiguration *pc);
|
||||
void handleTreeScanningFinished();
|
||||
void handleParsingSuccess(Internal::CMakeBuildConfiguration *bc);
|
||||
void handleParsingError(Internal::CMakeBuildConfiguration *bc);
|
||||
@@ -121,19 +104,21 @@ private:
|
||||
void updateProjectData(Internal::CMakeBuildConfiguration *bc);
|
||||
void updateQmlJSCodeModel();
|
||||
|
||||
Internal::CMakeProjectNode *
|
||||
generateProjectTree(const QList<const ProjectExplorer::FileNode*> &allFiles) const;
|
||||
|
||||
void createGeneratedCodeModelSupport();
|
||||
QStringList filesGeneratedFrom(const QString &sourceFile) const final;
|
||||
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
|
||||
void updateApplicationAndDeploymentTargets();
|
||||
|
||||
bool mustUpdateCMakeStateBeforeBuild();
|
||||
|
||||
// TODO probably need a CMake specific node structure
|
||||
QList<CMakeBuildTarget> m_buildTargets;
|
||||
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
|
||||
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
|
||||
|
||||
Internal::TreeScanner m_treeScanner;
|
||||
Internal::BuildDirManager m_buildDirManager;
|
||||
|
||||
bool m_waitingForScan = false;
|
||||
bool m_waitingForParse = false;
|
||||
@@ -144,6 +129,7 @@ private:
|
||||
mutable std::unique_ptr<Internal::CMakeProjectImporter> m_projectImporter;
|
||||
|
||||
QTimer m_delayedParsingTimer;
|
||||
int m_delayedParsingParameters = 0;
|
||||
|
||||
friend class Internal::CMakeBuildConfiguration;
|
||||
friend class Internal::CMakeBuildSettingsWidget;
|
||||
|
@@ -243,7 +243,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const Utils::FileName &impo
|
||||
}
|
||||
|
||||
QString errorMessage;
|
||||
const CMakeConfig config = BuildDirManager::parseConfiguration(cacheFile, &errorMessage);
|
||||
const CMakeConfig config = BuildDirManager::parseCMakeConfiguration(cacheFile, &errorMessage);
|
||||
if (config.isEmpty() || !errorMessage.isEmpty()) {
|
||||
qCDebug(cmInputLog()) << "Failed to read configuration from" << cacheFile << errorMessage;
|
||||
return { };
|
||||
|
@@ -24,7 +24,6 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "cmakeprojectmanager.h"
|
||||
#include "builddirmanager.h"
|
||||
#include "cmakebuildconfiguration.h"
|
||||
#include "cmakekitinformation.h"
|
||||
#include "cmakeprojectconstants.h"
|
||||
@@ -43,9 +42,6 @@
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
|
||||
#include <utils/qtcprocess.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <QAction>
|
||||
#include <QDateTime>
|
||||
#include <QIcon>
|
||||
@@ -121,19 +117,15 @@ void CMakeManager::updateCmakeActions()
|
||||
|
||||
void CMakeManager::clearCMakeCache(Project *project)
|
||||
{
|
||||
if (!project || !project->activeTarget())
|
||||
return;
|
||||
auto bc = qobject_cast<CMakeBuildConfiguration *>(project->activeTarget()->activeBuildConfiguration());
|
||||
if (!bc)
|
||||
CMakeProject *cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
|
||||
bc->clearCache();
|
||||
cmakeProject->clearCMakeCache();
|
||||
}
|
||||
|
||||
void CMakeManager::runCMake(Project *project)
|
||||
{
|
||||
if (!project)
|
||||
return;
|
||||
CMakeProject *cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
@@ -146,8 +138,6 @@ void CMakeManager::runCMake(Project *project)
|
||||
|
||||
void CMakeManager::rescanProject(Project *project)
|
||||
{
|
||||
if (!project)
|
||||
return;
|
||||
CMakeProject *cmakeProject = qobject_cast<CMakeProject *>(project);
|
||||
if (!cmakeProject || !cmakeProject->activeTarget() || !cmakeProject->activeTarget()->activeBuildConfiguration())
|
||||
return;
|
||||
|
@@ -2,9 +2,11 @@ DEFINES += CMAKEPROJECTMANAGER_LIBRARY
|
||||
include(../../qtcreatorplugin.pri)
|
||||
|
||||
HEADERS = builddirmanager.h \
|
||||
builddirparameters.h \
|
||||
builddirreader.h \
|
||||
cmakebuildinfo.h \
|
||||
cmakebuildstep.h \
|
||||
cmakebuildtarget.h \
|
||||
cmakeconfigitem.h \
|
||||
cmakeproject.h \
|
||||
cmakeprojectimporter.h \
|
||||
@@ -36,8 +38,10 @@ HEADERS = builddirmanager.h \
|
||||
treescanner.h
|
||||
|
||||
SOURCES = builddirmanager.cpp \
|
||||
builddirparameters.cpp \
|
||||
builddirreader.cpp \
|
||||
cmakebuildstep.cpp \
|
||||
cmakebuildtarget.cpp \
|
||||
cmakeconfigitem.cpp \
|
||||
cmakeproject.cpp \
|
||||
cmakeprojectimporter.cpp \
|
||||
|
@@ -200,6 +200,42 @@ QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
|
||||
});
|
||||
}
|
||||
|
||||
void ConfigModel::setConfiguration(const CMakeConfig &config)
|
||||
{
|
||||
setConfiguration(Utils::transform(config, [](const CMakeConfigItem &i) {
|
||||
ConfigModel::DataItem j;
|
||||
j.key = QString::fromUtf8(i.key);
|
||||
j.value = QString::fromUtf8(i.value);
|
||||
j.description = QString::fromUtf8(i.documentation);
|
||||
j.values = i.values;
|
||||
j.inCMakeCache = i.inCMakeCache;
|
||||
|
||||
j.isAdvanced = i.isAdvanced;
|
||||
j.isHidden = i.type == CMakeConfigItem::INTERNAL || i.type == CMakeConfigItem::STATIC;
|
||||
|
||||
switch (i.type) {
|
||||
case CMakeConfigItem::FILEPATH:
|
||||
j.type = ConfigModel::DataItem::FILE;
|
||||
break;
|
||||
case CMakeConfigItem::PATH:
|
||||
j.type = ConfigModel::DataItem::DIRECTORY;
|
||||
break;
|
||||
case CMakeConfigItem::BOOL:
|
||||
j.type = ConfigModel::DataItem::BOOLEAN;
|
||||
break;
|
||||
case CMakeConfigItem::STRING:
|
||||
j.type = ConfigModel::DataItem::STRING;
|
||||
break;
|
||||
default:
|
||||
j.type = ConfigModel::DataItem::UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return j;
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
void ConfigModel::setConfiguration(const QList<ConfigModel::InternalDataItem> &config)
|
||||
{
|
||||
QList<InternalDataItem> tmp = config;
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cmakeconfigitem.h"
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <utils/treemodel.h>
|
||||
|
||||
@@ -65,6 +67,7 @@ public:
|
||||
const DataItem::Type type = DataItem::UNKNOWN,
|
||||
const QString &description = QString(),
|
||||
const QStringList &values = QStringList());
|
||||
void setConfiguration(const CMakeConfig &config);
|
||||
void setConfiguration(const QList<DataItem> &config);
|
||||
void setKitConfiguration(const QHash<QString, QString> &kitConfig);
|
||||
void flush();
|
||||
@@ -80,6 +83,7 @@ public:
|
||||
|
||||
QList<DataItem> configurationChanges() const;
|
||||
|
||||
|
||||
private:
|
||||
class InternalDataItem : public DataItem
|
||||
{
|
||||
@@ -97,9 +101,9 @@ private:
|
||||
QString kitValue;
|
||||
};
|
||||
|
||||
void setConfiguration(const QList<InternalDataItem> &config);
|
||||
void generateTree();
|
||||
|
||||
void setConfiguration(const QList<InternalDataItem> &config);
|
||||
QList<InternalDataItem> m_configuration;
|
||||
QHash<QString, QString> m_kitConfiguration;
|
||||
|
||||
|
@@ -97,12 +97,15 @@ ServerModeReader::~ServerModeReader()
|
||||
stop();
|
||||
}
|
||||
|
||||
void ServerModeReader::setParameters(const BuildDirReader::Parameters &p)
|
||||
void ServerModeReader::setParameters(const BuildDirParameters &p)
|
||||
{
|
||||
QTC_ASSERT(p.cmakeTool, return);
|
||||
|
||||
BuildDirReader::setParameters(p);
|
||||
if (!m_cmakeServer) {
|
||||
m_cmakeServer.reset(new ServerMode(p.environment,
|
||||
p.sourceDirectory, p.buildDirectory, p.cmakeExecutable,
|
||||
p.sourceDirectory, p.buildDirectory,
|
||||
p.cmakeTool->cmakeExecutable(),
|
||||
p.generator, p.extraGenerator, p.platform, p.toolset,
|
||||
true, 1));
|
||||
connect(m_cmakeServer.get(), &ServerMode::errorOccured,
|
||||
@@ -135,14 +138,17 @@ void ServerModeReader::setParameters(const BuildDirReader::Parameters &p)
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerModeReader::isCompatible(const BuildDirReader::Parameters &p)
|
||||
bool ServerModeReader::isCompatible(const BuildDirParameters &p)
|
||||
{
|
||||
// Server mode connection got lost, reset...
|
||||
if (!m_parameters.cmakeExecutable.isEmpty() && !m_cmakeServer)
|
||||
if (!p.cmakeTool)
|
||||
return false;
|
||||
|
||||
return p.cmakeHasServerMode
|
||||
&& p.cmakeExecutable == m_parameters.cmakeExecutable
|
||||
// Server mode connection got lost, reset...
|
||||
if (!m_parameters.cmakeTool->cmakeExecutable().isEmpty() && !m_cmakeServer)
|
||||
return false;
|
||||
|
||||
return p.cmakeTool->hasServerMode()
|
||||
&& p.cmakeTool->cmakeExecutable() == m_parameters.cmakeTool->cmakeExecutable()
|
||||
&& p.environment == m_parameters.environment
|
||||
&& p.generator == m_parameters.generator
|
||||
&& p.extraGenerator == m_parameters.extraGenerator
|
||||
@@ -154,16 +160,22 @@ bool ServerModeReader::isCompatible(const BuildDirReader::Parameters &p)
|
||||
|
||||
void ServerModeReader::resetData()
|
||||
{
|
||||
m_hasData = false;
|
||||
m_cmakeConfiguration.clear();
|
||||
// m_cmakeFiles: Keep these!
|
||||
m_cmakeInputsFileNodes.clear();
|
||||
qDeleteAll(m_projects); // Also deletes targets and filegroups that are its children!
|
||||
m_projects.clear();
|
||||
m_targets.clear();
|
||||
m_fileGroups.clear();
|
||||
}
|
||||
|
||||
void ServerModeReader::parse(bool force)
|
||||
void ServerModeReader::parse(bool forceConfiguration)
|
||||
{
|
||||
emit configurationStarted();
|
||||
|
||||
QTC_ASSERT(m_cmakeServer, return);
|
||||
QVariantMap extra;
|
||||
if (force || !QDir(m_parameters.buildDirectory.toString()).exists("CMakeCache.txt")) {
|
||||
if (forceConfiguration || !QDir(m_parameters.buildDirectory.toString()).exists("CMakeCache.txt")) {
|
||||
QStringList cacheArguments = transform(m_parameters.configuration,
|
||||
[this](const CMakeConfigItem &i) {
|
||||
return i.toArgument(m_parameters.expander);
|
||||
@@ -208,12 +220,7 @@ bool ServerModeReader::isParsing() const
|
||||
return static_cast<bool>(m_future);
|
||||
}
|
||||
|
||||
bool ServerModeReader::hasData() const
|
||||
{
|
||||
return m_hasData;
|
||||
}
|
||||
|
||||
QList<CMakeBuildTarget> ServerModeReader::buildTargets() const
|
||||
QList<CMakeBuildTarget> ServerModeReader::takeBuildTargets()
|
||||
{
|
||||
const QList<CMakeBuildTarget> result = transform(m_targets, [](const Target *t) -> CMakeBuildTarget {
|
||||
CMakeBuildTarget ct;
|
||||
@@ -246,8 +253,8 @@ QList<CMakeBuildTarget> ServerModeReader::buildTargets() const
|
||||
|
||||
CMakeConfig ServerModeReader::takeParsedConfiguration()
|
||||
{
|
||||
CMakeConfig config = m_cmakeCache;
|
||||
m_cmakeCache.clear();
|
||||
CMakeConfig config = m_cmakeConfiguration;
|
||||
m_cmakeConfiguration.clear();
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -372,11 +379,6 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
: CppTools::ProjectPart::Library);
|
||||
rpps.append(rpp);
|
||||
}
|
||||
|
||||
qDeleteAll(m_projects); // Not used anymore!
|
||||
m_projects.clear();
|
||||
m_targets.clear();
|
||||
m_fileGroups.clear();
|
||||
}
|
||||
|
||||
void ServerModeReader::handleReply(const QVariantMap &data, const QString &inReplyTo)
|
||||
@@ -415,7 +417,6 @@ void ServerModeReader::handleReply(const QVariantMap &data, const QString &inRep
|
||||
m_future->reportFinished();
|
||||
m_future.reset();
|
||||
}
|
||||
m_hasData = true;
|
||||
Core::MessageManager::write(tr("CMake Project was parsed successfully."));
|
||||
emit dataAvailable();
|
||||
}
|
||||
@@ -672,7 +673,7 @@ void ServerModeReader::extractCacheData(const QVariantMap &data)
|
||||
item.values = CMakeConfigItem::cmakeSplitValue(properties.value("STRINGS").toString(), true);
|
||||
config.append(item);
|
||||
}
|
||||
m_cmakeCache = config;
|
||||
m_cmakeConfiguration = config;
|
||||
}
|
||||
|
||||
void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
|
||||
|
@@ -33,10 +33,11 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ProjectExplorer { class ProjectNode; }
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
class ServerModeReader : public BuildDirReader
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -45,18 +46,17 @@ public:
|
||||
ServerModeReader();
|
||||
~ServerModeReader() final;
|
||||
|
||||
void setParameters(const Parameters &p) final;
|
||||
void setParameters(const BuildDirParameters &p) final;
|
||||
|
||||
bool isCompatible(const Parameters &p) final;
|
||||
bool isCompatible(const BuildDirParameters &p) final;
|
||||
void resetData() final;
|
||||
void parse(bool force) final;
|
||||
void parse(bool forceConfiguration) final;
|
||||
void stop() final;
|
||||
|
||||
bool isReady() const final;
|
||||
bool isParsing() const final;
|
||||
bool hasData() const final;
|
||||
|
||||
QList<CMakeBuildTarget> buildTargets() const final;
|
||||
QList<CMakeBuildTarget> takeBuildTargets() final;
|
||||
CMakeConfig takeParsedConfiguration() final;
|
||||
void generateProjectTree(CMakeProjectNode *root,
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles) final;
|
||||
@@ -160,21 +160,19 @@ private:
|
||||
const QList<ProjectExplorer::FileNode *> knownHeaders,
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles);
|
||||
|
||||
bool m_hasData = false;
|
||||
|
||||
std::unique_ptr<ServerMode> m_cmakeServer;
|
||||
std::unique_ptr<QFutureInterface<void>> m_future;
|
||||
|
||||
int m_progressStepMinimum = 0;
|
||||
int m_progressStepMaximum = 1000;
|
||||
|
||||
CMakeConfig m_cmakeCache;
|
||||
CMakeConfig m_cmakeConfiguration;
|
||||
|
||||
QSet<Utils::FileName> m_cmakeFiles;
|
||||
QList<ProjectExplorer::FileNode *> m_cmakeInputsFileNodes;
|
||||
|
||||
QList<Project *> m_projects;
|
||||
mutable QList<Target *> m_targets;
|
||||
QList<Target *> m_targets;
|
||||
QList<FileGroup *> m_fileGroups;
|
||||
|
||||
CMakeParser m_parser;
|
||||
|
@@ -130,7 +130,9 @@ TeaLeafReader::TeaLeafReader()
|
||||
{
|
||||
connect(EditorManager::instance(), &EditorManager::aboutToSave,
|
||||
this, [this](const IDocument *document) {
|
||||
if (m_cmakeFiles.contains(document->filePath()) || !m_parameters.isAutorun)
|
||||
if (m_cmakeFiles.contains(document->filePath())
|
||||
|| !m_parameters.cmakeTool
|
||||
|| !m_parameters.cmakeTool->isAutoRun())
|
||||
emit dirty();
|
||||
});
|
||||
|
||||
@@ -150,15 +152,15 @@ TeaLeafReader::~TeaLeafReader()
|
||||
resetData();
|
||||
}
|
||||
|
||||
bool TeaLeafReader::isCompatible(const BuildDirReader::Parameters &p)
|
||||
bool TeaLeafReader::isCompatible(const BuildDirParameters &p)
|
||||
{
|
||||
return !p.cmakeHasServerMode;
|
||||
if (!p.cmakeTool)
|
||||
return false;
|
||||
return !p.cmakeTool->hasServerMode();
|
||||
}
|
||||
|
||||
void TeaLeafReader::resetData()
|
||||
{
|
||||
m_hasData = false;
|
||||
|
||||
qDeleteAll(m_watchedFiles);
|
||||
m_watchedFiles.clear();
|
||||
|
||||
@@ -188,11 +190,11 @@ static QString findCbpFile(const QDir &directory)
|
||||
return file;
|
||||
}
|
||||
|
||||
void TeaLeafReader::parse(bool force)
|
||||
void TeaLeafReader::parse(bool forceConfiguration)
|
||||
{
|
||||
const QString cbpFile = findCbpFile(QDir(m_parameters.buildDirectory.toString()));
|
||||
const QFileInfo cbpFileFi = cbpFile.isEmpty() ? QFileInfo() : QFileInfo(cbpFile);
|
||||
if (!cbpFileFi.exists() || force) {
|
||||
if (!cbpFileFi.exists() || forceConfiguration) {
|
||||
// Initial create:
|
||||
startCMake(toArguments(m_parameters.configuration, m_parameters.expander));
|
||||
return;
|
||||
@@ -206,7 +208,6 @@ void TeaLeafReader::parse(bool force)
|
||||
startCMake(QStringList());
|
||||
} else {
|
||||
extractData();
|
||||
m_hasData = true;
|
||||
emit dataAvailable();
|
||||
}
|
||||
}
|
||||
@@ -228,12 +229,7 @@ bool TeaLeafReader::isParsing() const
|
||||
return m_cmakeProcess && m_cmakeProcess->state() != QProcess::NotRunning;
|
||||
}
|
||||
|
||||
bool TeaLeafReader::hasData() const
|
||||
{
|
||||
return m_hasData;
|
||||
}
|
||||
|
||||
QList<CMakeBuildTarget> TeaLeafReader::buildTargets() const
|
||||
QList<CMakeBuildTarget> TeaLeafReader::takeBuildTargets()
|
||||
{
|
||||
return m_buildTargets;
|
||||
}
|
||||
@@ -247,7 +243,7 @@ CMakeConfig TeaLeafReader::takeParsedConfiguration()
|
||||
return { };
|
||||
|
||||
QString errorMessage;
|
||||
CMakeConfig result = BuildDirManager::parseConfiguration(cacheFile, &errorMessage);
|
||||
CMakeConfig result = BuildDirManager::parseCMakeConfiguration(cacheFile, &errorMessage);
|
||||
|
||||
if (!errorMessage.isEmpty()) {
|
||||
emit errorOccured(errorMessage);
|
||||
@@ -412,6 +408,8 @@ void TeaLeafReader::cleanUpProcess()
|
||||
|
||||
void TeaLeafReader::extractData()
|
||||
{
|
||||
QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return);
|
||||
|
||||
const FileName srcDir = m_parameters.sourceDirectory;
|
||||
const FileName bldDir = m_parameters.buildDirectory;
|
||||
const FileName topCMake = Utils::FileName(srcDir).appendPath("CMakeLists.txt");
|
||||
@@ -437,7 +435,7 @@ void TeaLeafReader::extractData()
|
||||
// setFolderName
|
||||
CMakeCbpParser cbpparser;
|
||||
// Parsing
|
||||
if (!cbpparser.parseCbpFile(m_parameters.pathMapper, cbpFile, srcDir))
|
||||
if (!cbpparser.parseCbpFile(m_parameters.cmakeTool->pathMapper(), cbpFile, srcDir))
|
||||
return;
|
||||
|
||||
m_projectName = cbpparser.projectName();
|
||||
@@ -460,6 +458,8 @@ void TeaLeafReader::extractData()
|
||||
|
||||
void TeaLeafReader::startCMake(const QStringList &configurationArguments)
|
||||
{
|
||||
QTC_ASSERT(m_parameters.isValid() && m_parameters.cmakeTool, return);
|
||||
|
||||
const FileName buildDirectory = m_parameters.buildDirectory;
|
||||
QTC_ASSERT(!m_cmakeProcess, return);
|
||||
QTC_ASSERT(!m_parser, return);
|
||||
@@ -503,7 +503,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
|
||||
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||
|
||||
MessageManager::write(tr("Running \"%1 %2\" in %3.")
|
||||
.arg(m_parameters.cmakeExecutable.toUserOutput())
|
||||
.arg(m_parameters.cmakeTool->cmakeExecutable().toUserOutput())
|
||||
.arg(args)
|
||||
.arg(buildDirectory.toUserOutput()));
|
||||
|
||||
@@ -513,7 +513,7 @@ void TeaLeafReader::startCMake(const QStringList &configurationArguments)
|
||||
tr("Configuring \"%1\"").arg(m_parameters.projectName),
|
||||
"CMake.Configure");
|
||||
|
||||
m_cmakeProcess->setCommand(m_parameters.cmakeExecutable.toString(), args);
|
||||
m_cmakeProcess->setCommand(m_parameters.cmakeTool->cmakeExecutable().toString(), args);
|
||||
emit configurationStarted();
|
||||
m_cmakeProcess->start();
|
||||
}
|
||||
@@ -549,7 +549,6 @@ void TeaLeafReader::cmakeFinished(int code, QProcess::ExitStatus status)
|
||||
delete m_future;
|
||||
m_future = nullptr;
|
||||
|
||||
m_hasData = true;
|
||||
emit dataAvailable();
|
||||
}
|
||||
|
||||
@@ -663,7 +662,7 @@ bool TeaLeafReader::extractFlagsFromNinja(const CMakeBuildTarget &buildTarget,
|
||||
// found
|
||||
// Get "all" target's working directory
|
||||
QByteArray ninjaFile;
|
||||
QString buildNinjaFile = buildTargets().at(0).workingDirectory.toString();
|
||||
QString buildNinjaFile = takeBuildTargets().at(0).workingDirectory.toString();
|
||||
buildNinjaFile += "/build.ninja";
|
||||
QFile buildNinja(buildNinjaFile);
|
||||
if (buildNinja.exists()) {
|
||||
|
@@ -46,15 +46,14 @@ public:
|
||||
TeaLeafReader();
|
||||
~TeaLeafReader() final;
|
||||
|
||||
bool isCompatible(const Parameters &p) final;
|
||||
bool isCompatible(const BuildDirParameters &p) final;
|
||||
void resetData() final;
|
||||
void parse(bool force) final;
|
||||
void parse(bool forceConfiguration) final;
|
||||
void stop() final;
|
||||
|
||||
bool isParsing() const final;
|
||||
bool hasData() const final;
|
||||
|
||||
QList<CMakeBuildTarget> buildTargets() const final;
|
||||
QList<CMakeBuildTarget> takeBuildTargets() final;
|
||||
CMakeConfig takeParsedConfiguration() final;
|
||||
void generateProjectTree(CMakeProjectNode *root,
|
||||
const QList<const ProjectExplorer::FileNode *> &allFiles) final;
|
||||
@@ -80,8 +79,6 @@ private:
|
||||
ProjectExplorer::IOutputParser *m_parser = nullptr;
|
||||
QFutureInterface<void> *m_future = nullptr;
|
||||
|
||||
bool m_hasData = false;
|
||||
|
||||
QSet<Utils::FileName> m_cmakeFiles;
|
||||
QString m_projectName;
|
||||
QList<CMakeBuildTarget> m_buildTargets;
|
||||
|
Reference in New Issue
Block a user