Commit 76a050cb authored by Tobias Hunger's avatar Tobias Hunger

CMake: Move BuildDirManager from the project into the buildconfiguration

Change-Id: I90126ff22dd394eba4145db142b3914d211af476
Reviewed-by: default avatarTobias Hunger <tobias.hunger@theqtcompany.com>
parent 34fd3256
......@@ -57,39 +57,40 @@ class CMakeTool;
namespace Internal {
class CMakeBuildConfiguration;
class BuildDirManager : public QObject
{
Q_OBJECT
public:
BuildDirManager(const Utils::FileName &sourceDir, const ProjectExplorer::Kit *k,
const CMakeConfig &inputConfig, const Utils::Environment &env,
const Utils::FileName &buildDir);
BuildDirManager(const CMakeBuildConfiguration *bc);
~BuildDirManager() override;
const ProjectExplorer::Kit *kit() const { return m_kit; }
const Utils::FileName buildDirectory() const { return m_buildDir; }
const Utils::FileName sourceDirectory() const { return m_sourceDir; }
bool isBusy() const;
const ProjectExplorer::Kit *kit() const;
const Utils::FileName buildDirectory() const;
const Utils::FileName sourceDirectory() const;
const CMakeConfig cmakeConfiguration() const;
bool isParsing() const;
void parse();
void forceReparse();
void setInputConfiguration(const CMakeConfig &config);
void resetData();
bool isProjectFile(const Utils::FileName &fileName) const;
QString projectName() const;
QList<CMakeBuildTarget> buildTargets() const;
QList<ProjectExplorer::FileNode *> files() const;
QList<ProjectExplorer::FileNode *> files();
void clearFiles();
CMakeConfig configuration() const;
signals:
void parsingStarted() const;
void configurationStarted() const;
void dataAvailable() const;
void errorOccured(const QString &err) const;
private:
void stopProcess();
void extractData();
void startCMake(CMakeTool *tool, const QString &generator, const CMakeConfig &config);
......@@ -100,14 +101,9 @@ private:
CMakeConfig parseConfiguration() const;
const Utils::FileName m_sourceDir;
Utils::FileName m_buildDir;
Utils::FileName m_parsedSourceDir;
const ProjectExplorer::Kit *const m_kit;
Utils::Environment m_environment;
CMakeConfig m_inputConfig;
bool m_hasData = false;
QTemporaryDir *m_tempDir = nullptr;
const CMakeBuildConfiguration *m_buildConfiguration = nullptr;
Utils::QtcProcess *m_cmakeProcess = nullptr;
QSet<Utils::FileName> m_watchedFiles;
......
......@@ -25,6 +25,7 @@
#include "cmakebuildconfiguration.h"
#include "builddirmanager.h"
#include "cmakebuildinfo.h"
#include "cmakebuildstep.h"
#include "cmakekitinformation.h"
......@@ -75,10 +76,32 @@ static FileName shadowBuildDirectory(const FileName &projectFilePath, const Kit
CMakeBuildConfiguration::CMakeBuildConfiguration(ProjectExplorer::Target *parent) :
BuildConfiguration(parent, Core::Id(Constants::CMAKE_BC_ID))
{
CMakeProject *project = static_cast<CMakeProject *>(parent->project());
auto project = static_cast<CMakeProject *>(parent->project());
setBuildDirectory(shadowBuildDirectory(project->projectFilePath(),
parent->kit(),
displayName(), BuildConfiguration::Unknown));
m_buildDirManager = new BuildDirManager(this);
connect(m_buildDirManager, &BuildDirManager::dataAvailable,
this, &CMakeBuildConfiguration::dataAvailable);
connect(m_buildDirManager, &BuildDirManager::errorOccured,
this, &CMakeBuildConfiguration::setError);
connect(m_buildDirManager, &BuildDirManager::configurationStarted,
this, [this]() { m_completeConfigurationCache.clear(); emit parsingStarted(); });
connect(this, &CMakeBuildConfiguration::environmentChanged,
m_buildDirManager, &BuildDirManager::forceReparse);
connect(this, &CMakeBuildConfiguration::buildDirectoryChanged,
m_buildDirManager, &BuildDirManager::parse);
connect(target(), &Target::kitChanged, m_buildDirManager, &BuildDirManager::forceReparse);
connect(this, &CMakeBuildConfiguration::parsingStarted, project, &CMakeProject::handleParsingStarted);
connect(this, &CMakeBuildConfiguration::dataAvailable, project, &CMakeProject::parseCMakeOutput);
}
CMakeBuildConfiguration::~CMakeBuildConfiguration()
{
m_buildDirManager->deleteLater(); // Do not block while waiting for cmake...
}
bool CMakeBuildConfiguration::isEnabled() const
......@@ -139,6 +162,102 @@ bool CMakeBuildConfiguration::fromMap(const QVariantMap &map)
return true;
}
BuildDirManager *CMakeBuildConfiguration::buildDirManager() const
{
return m_buildDirManager;
}
bool CMakeBuildConfiguration::isParsing() const
{
return m_buildDirManager && m_buildDirManager->isParsing();
}
void CMakeBuildConfiguration::parse()
{
m_buildDirManager->parse();
}
void CMakeBuildConfiguration::resetData()
{
m_buildDirManager->resetData();
}
QList<ConfigModel::DataItem> CMakeBuildConfiguration::completeCMakeConfiguration() const
{
if (m_buildDirManager->isParsing())
return QList<ConfigModel::DataItem>();
if (m_completeConfigurationCache.isEmpty())
m_completeConfigurationCache = m_buildDirManager->configuration();
return Utils::transform(m_completeConfigurationCache, [](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.isAdvanced = i.isAdvanced;
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 CMakeBuildConfiguration::setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items)
{
if (m_buildDirManager->isParsing())
return;
const CMakeConfig newConfig = Utils::transform(items, [](const ConfigModel::DataItem &i) {
CMakeConfigItem ni;
ni.key = i.key.toUtf8();
ni.value = i.value.toUtf8();
ni.documentation = i.description.toUtf8();
ni.isAdvanced = i.isAdvanced;
switch (i.type) {
case CMakeProjectManager::ConfigModel::DataItem::BOOLEAN:
ni.type = CMakeConfigItem::BOOL;
break;
case CMakeProjectManager::ConfigModel::DataItem::FILE:
ni.type = CMakeConfigItem::FILEPATH;
break;
case CMakeProjectManager::ConfigModel::DataItem::DIRECTORY:
ni.type = CMakeConfigItem::PATH;
break;
case CMakeProjectManager::ConfigModel::DataItem::STRING:
ni.type = CMakeConfigItem::STRING;
break;
case CMakeProjectManager::ConfigModel::DataItem::UNKNOWN:
default:
ni.type = CMakeConfigItem::INTERNAL;
break;
}
return ni;
});
// There is a buildDirManager, so there must also be an active BC:
const CMakeConfig config = cmakeConfiguration() + newConfig;
setCMakeConfiguration(config);
m_buildDirManager->forceReparse();
}
void CMakeBuildConfiguration::emitBuildTypeChanged()
{
emit buildTypeChanged();
......
......@@ -26,6 +26,7 @@
#pragma once
#include "cmakeconfigitem.h"
#include "configmodel.h"
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/abi.h>
......@@ -38,7 +39,9 @@ class CMakeProject;
namespace Internal {
class BuildDirManager;
class CMakeBuildConfigurationFactory;
class CMakeBuildSettingsWidget;
class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
{
......@@ -47,6 +50,7 @@ class CMakeBuildConfiguration : public ProjectExplorer::BuildConfiguration
public:
CMakeBuildConfiguration(ProjectExplorer::Target *parent);
~CMakeBuildConfiguration();
bool isEnabled() const override;
QString disabledReason() const override;
......@@ -60,24 +64,44 @@ public:
void emitBuildTypeChanged();
void setCMakeConfiguration(const CMakeConfig &config);
bool hasCMakeConfiguration() const;
CMakeConfig cmakeConfiguration() const;
void setError(const QString &message);
QString error() const;
BuildDirManager *buildDirManager() const;
bool isParsing() const;
void parse();
void resetData();
signals:
void errorOccured(const QString &message);
void parsingStarted();
void dataAvailable();
protected:
CMakeBuildConfiguration(ProjectExplorer::Target *parent, CMakeBuildConfiguration *source);
bool fromMap(const QVariantMap &map) override;
private:
QList<ConfigModel::DataItem> completeCMakeConfiguration() const;
void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items);
void setError(const QString &message);
QString m_initialArguments;
CMakeConfig m_configuration;
QString m_error;
friend class CMakeProjectManager::CMakeProject;
mutable QList<CMakeConfigItem> m_completeConfigurationCache;
BuildDirManager *m_buildDirManager = nullptr;
friend class CMakeBuildSettingsWidget;
friend class CMakeProject;
};
class CMakeBuildConfigurationFactory : public ProjectExplorer::IBuildConfigurationFactory
......
......@@ -84,9 +84,9 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
buildDirChooser->setBaseFileName(project->projectDirectory());
buildDirChooser->setFileName(bc->buildDirectory());
connect(buildDirChooser, &Utils::PathChooser::rawPathChanged, this,
[this, project](const QString &path) {
[this](const QString &path) {
m_configModel->flush(); // clear out config cache...
project->changeBuildDirectory(m_buildConfiguration, path);
m_buildConfiguration->setBuildDirectory(Utils::FileName::fromString(path));
});
int row = 0;
......@@ -123,7 +123,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setMinimumHeight(300);
m_configView->setRootIsDecorated(false);
m_configView->setUniformRowHeights(true);
new Utils::HeaderViewStretcher(m_configView->header(), 1);
auto stretcher = new Utils::HeaderViewStretcher(m_configView->header(), 1);
m_configView->setSelectionMode(QAbstractItemView::SingleSelection);
m_configView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_configView->setFrameShape(QFrame::NoFrame);
......@@ -166,13 +166,18 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
updateButtonState();
m_showProgressTimer.start();
});
connect(project, &CMakeProject::buildDirectoryDataAvailable,
this, [this, project, buildDirChooser](ProjectExplorer::BuildConfiguration *bc) {
if (m_buildConfiguration->isParsing())
m_showProgressTimer.start();
else
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
connect(m_buildConfiguration, &CMakeBuildConfiguration::dataAvailable,
this, [this, buildDirChooser, stretcher]() {
updateButtonState();
if (m_buildConfiguration == bc) {
m_configModel->setConfiguration(project->currentCMakeConfiguration());
buildDirChooser->triggerChanged(); // refresh valid state...
}
m_configModel->setConfiguration(m_buildConfiguration->completeCMakeConfiguration());
stretcher->stretch();
buildDirChooser->triggerChanged(); // refresh valid state...
m_showProgressTimer.stop();
m_progressIndicator->hide();
});
......@@ -186,8 +191,8 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
this, &CMakeBuildSettingsWidget::updateAdvancedCheckBox);
connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges);
connect(m_reconfigureButton, &QPushButton::clicked, this, [this, project]() {
project->setCurrentCMakeConfiguration(m_configModel->configurationChanges());
connect(m_reconfigureButton, &QPushButton::clicked, this, [this]() {
m_buildConfiguration->setCurrentCMakeConfiguration(m_configModel->configurationChanges());
});
connect(m_editButton, &QPushButton::clicked, this, [this]() {
QModelIndex idx = m_configView->currentIndex();
......@@ -218,8 +223,7 @@ void CMakeBuildSettingsWidget::setError(const QString &message)
void CMakeBuildSettingsWidget::updateButtonState()
{
auto project = static_cast<CMakeProject *>(m_buildConfiguration->target()->project());
const bool isParsing = project->isParsing();
const bool isParsing = m_buildConfiguration->isParsing();
const bool hasChanges = m_configModel->hasChanges();
m_resetButton->setEnabled(hasChanges && !isParsing);
m_reconfigureButton->setEnabled((hasChanges || m_configModel->hasCMakeChanges()) && !isParsing);
......
......@@ -72,12 +72,12 @@ const char ADD_RUNCONFIGURATION_TEXT[] = "Current executable";
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl) : AbstractProcessStep(bsl, Core::Id(MS_ID))
{
ctor();
ctor(bsl);
}
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Core::Id id) : AbstractProcessStep(bsl, id)
{
ctor();
ctor(bsl);
}
CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, CMakeBuildStep *bs) :
......@@ -86,10 +86,10 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, CMakeBuildStep *bs) :
m_toolArguments(bs->m_toolArguments),
m_addRunConfigurationArgument(bs->m_addRunConfigurationArgument)
{
ctor();
ctor(bsl);
}
void CMakeBuildStep::ctor()
void CMakeBuildStep::ctor(BuildStepList *bsl)
{
m_percentProgress = QRegExp(QLatin1String("^\\[\\s*(\\d*)%\\]"));
m_ninjaProgress = QRegExp(QLatin1String("^\\[\\s*(\\d*)/\\s*(\\d*)"));
......@@ -97,9 +97,15 @@ void CMakeBuildStep::ctor()
//: Default display name for the cmake make step.
setDefaultDisplayName(tr("Make"));
auto bc = qobject_cast<CMakeBuildConfiguration *>(bsl->parent());
if (!bc) {
auto t = qobject_cast<Target *>(bsl->parent()->parent());
QTC_ASSERT(t, return);
bc = qobject_cast<CMakeBuildConfiguration *>(t->activeBuildConfiguration());
}
connect(target(), &Target::kitChanged, this, &CMakeBuildStep::cmakeCommandChanged);
connect(static_cast<CMakeProject *>(project()), &CMakeProject::buildDirectoryDataAvailable,
this, &CMakeBuildStep::buildTargetsChanged);
connect(bc, &CMakeBuildConfiguration::dataAvailable, this, &CMakeBuildStep::handleBuildTargetChanges);
}
CMakeBuildConfiguration *CMakeBuildStep::cmakeBuildConfiguration() const
......@@ -117,12 +123,13 @@ CMakeRunConfiguration *CMakeBuildStep::targetsActiveRunConfiguration() const
return qobject_cast<CMakeRunConfiguration *>(target()->activeRunConfiguration());
}
void CMakeBuildStep::buildTargetsChanged()
void CMakeBuildStep::handleBuildTargetChanges()
{
const QStringList filteredTargets
= Utils::filtered(static_cast<CMakeProject *>(project())->buildTargetTitles(),
[this](const QString &s) { return m_buildTargets.contains(s); });
setBuildTargets(filteredTargets);
emit buildTargetsChanged();
}
QVariantMap CMakeBuildStep::toMap() const
......@@ -401,7 +408,7 @@ CMakeBuildStepConfigWidget::CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, &CMakeBuildStepConfigWidget::updateDetails);
connect(pro, &CMakeProject::buildDirectoryDataAvailable, this, &CMakeBuildStepConfigWidget::buildTargetsChanged);
connect(m_buildStep, &CMakeBuildStep::buildTargetsChanged, this, &CMakeBuildStepConfigWidget::buildTargetsChanged);
connect(m_buildStep, &CMakeBuildStep::targetsToBuildChanged, this, &CMakeBuildStepConfigWidget::selectedBuildTargetsChanged);
connect(pro, &CMakeProject::environmentChanged, this, &CMakeBuildStepConfigWidget::updateDetails);
}
......
......@@ -83,6 +83,7 @@ public:
signals:
void cmakeCommandChanged();
void targetsToBuildChanged();
void buildTargetsChanged();
protected:
void processStarted() override;
......@@ -97,9 +98,9 @@ protected:
void stdOutput(const QString &line) override;
private:
void ctor();
void ctor(ProjectExplorer::BuildStepList *bsl);
void buildTargetsChanged();
void handleBuildTargetChanges();
CMakeRunConfiguration *targetsActiveRunConfiguration() const;
QRegExp m_percentProgress;
......
......@@ -27,7 +27,6 @@
#include "cmake_global.h"
#include "cmakeprojectnodes.h"
#include "configmodel.h"
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/project.h>
......@@ -104,39 +103,27 @@ public:
CMakeBuildTarget buildTargetForTitle(const QString &title);
bool isProjectFile(const Utils::FileName &fileName);
bool needsConfiguration() const override;
bool requiresTargetPanel() const override;
bool supportsKit(ProjectExplorer::Kit *k, QString *errorMessage = 0) const override;
void runCMake();
bool isParsing() const;
QList<ConfigModel::DataItem> currentCMakeConfiguration() const;
void setCurrentCMakeConfiguration(const QList<ConfigModel::DataItem> &items);
signals:
/// emitted when parsing starts:
/// emitted when cmake is running:
void parsingStarted();
/// emitted after parsing
void buildDirectoryDataAvailable(ProjectExplorer::BuildConfiguration *bc);
protected:
RestoreResult fromMap(const QVariantMap &map, QString *errorMessage) override;
bool setupTarget(ProjectExplorer::Target *t) override;
// called by CMakeBuildSettingsWidget
void changeBuildDirectory(Internal::CMakeBuildConfiguration *bc, const QString &newBuildDirectory);
private:
void handleKitChanges();
void handleActiveTargetChanged();
void handleActiveBuildConfigurationChanged();
void handleParsingStarted();
void parseCMakeOutput();
void activeTargetHasChanged(ProjectExplorer::Target *target);
void changeActiveBuildConfiguration(ProjectExplorer::BuildConfiguration*);
void updateRunConfigurations();
void buildTree(Internal::CMakeProjectNode *rootNode, QList<ProjectExplorer::FileNode *> list);
......@@ -150,13 +137,14 @@ private:
bool extractCXXFlagsFromMake(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
bool extractCXXFlagsFromNinja(const CMakeBuildTarget &buildTarget, QHash<QString, QStringList> &cache);
ProjectExplorer::Target *m_activeTarget = 0;
Internal::BuildDirManager *m_buildDirManager = 0;
ProjectExplorer::Target *m_connectedTarget = nullptr;
// TODO probably need a CMake specific node structure
QList<CMakeBuildTarget> m_buildTargets;
QFuture<void> m_codeModelFuture;
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
friend class Internal::CMakeBuildConfiguration;
};
} // namespace CMakeProjectManager
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment