Merge remote-tracking branch 'origin/4.5'

Change-Id: Iceaa4ca40b5318744bde8a76c6d3ccca08df71bb
This commit is contained in:
Eike Ziller
2017-10-25 16:07:21 +02:00
108 changed files with 964 additions and 452 deletions

View File

@@ -66,6 +66,7 @@ Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters &paramet
const Utils::FileName bdir = parameters.buildDirectory;
const CMakeTool *cmake = parameters.cmakeTool;
if (bdir.exists()) {
m_buildDirToTempDir.erase(bdir);
return bdir;
} else {
if (cmake && cmake->autoCreateBuildDirectory()) {
@@ -74,14 +75,19 @@ Utils::FileName BuildDirManager::workDirectory(const BuildDirParameters &paramet
return bdir;
}
}
if (!m_tempDir) {
m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX"));
if (!m_tempDir->isValid()) {
auto tmpDirIt = m_buildDirToTempDir.find(bdir);
if (tmpDirIt == m_buildDirToTempDir.end()) {
auto ret = m_buildDirToTempDir.emplace(std::make_pair(bdir, std::make_unique<Utils::TemporaryDirectory>("qtc-cmake-XXXXXXXX")));
QTC_ASSERT(ret.second, return bdir);
tmpDirIt = ret.first;
if (!tmpDirIt->second->isValid()) {
emitErrorOccured(tr("Failed to create temporary directory \"%1\".")
.arg(QDir::toNativeSeparators(m_tempDir->path())));
.arg(QDir::toNativeSeparators(tmpDirIt->second->path())));
return bdir;
}
}
return Utils::FileName::fromString(m_tempDir->path());
return Utils::FileName::fromString(tmpDirIt->second->path());
}
void BuildDirManager::emitDataAvailable()
@@ -198,14 +204,20 @@ void BuildDirManager::setParametersAndRequestParse(const BuildDirParameters &par
BuildDirReader *old = m_reader.get();
m_parameters = parameters;
m_parameters.buildDirectory = workDirectory(parameters);
m_parameters.workDirectory = workDirectory(parameters);
updateReaderType(m_parameters,
[this, old, newReaderReparseOptions, existingReaderReparseOptions]() {
if (old != m_reader.get())
emit requestReparse(newReaderReparseOptions);
else
emit requestReparse(existingReaderReparseOptions);
int options = REPARSE_DEFAULT;
if (old != m_reader.get()) {
options = newReaderReparseOptions;
} else {
if (!QFileInfo::exists(m_parameters.workDirectory.toString() + "/CMakeCache.txt"))
options = newReaderReparseOptions;
else
options = existingReaderReparseOptions;
}
emit requestReparse(options);
});
}
@@ -239,16 +251,17 @@ bool BuildDirManager::persistCMakeState()
{
QTC_ASSERT(m_parameters.isValid(), return false);
if (!m_tempDir)
if (m_parameters.workDirectory == m_parameters.buildDirectory)
return false;
const Utils::FileName buildDir = m_parameters.buildDirectory;
QDir dir(buildDir.toString());
dir.mkpath(buildDir.toString());
m_tempDir.reset(nullptr);
emit requestReparse(REPARSE_URGENT | REPARSE_FORCE_CONFIGURATION | REPARSE_CHECK_CONFIGURATION);
BuildDirParameters newParameters = m_parameters;
newParameters.workDirectory.clear();
setParametersAndRequestParse(newParameters, REPARSE_URGENT | REPARSE_FORCE_CONFIGURATION | REPARSE_CHECK_CONFIGURATION,
REPARSE_FAIL);
return true;
}
@@ -291,8 +304,8 @@ void BuildDirManager::clearCache()
QTC_ASSERT(m_parameters.isValid(), return);
QTC_ASSERT(!m_isHandlingError, return);
auto cmakeCache = workDirectory(m_parameters).appendPath("CMakeCache.txt");
auto cmakeFiles = workDirectory(m_parameters).appendPath("CMakeFiles");
auto cmakeCache = m_parameters.workDirectory.appendPath("CMakeCache.txt");
auto cmakeFiles = m_parameters.workDirectory.appendPath("CMakeFiles");
const bool mustCleanUp = cmakeCache.exists() || cmakeFiles.exists();
if (!mustCleanUp)
@@ -367,7 +380,7 @@ bool BuildDirManager::checkConfiguration()
{
QTC_ASSERT(m_parameters.isValid(), return false);
if (m_tempDir) // always throw away changes in the tmpdir!
if (m_parameters.workDirectory != m_parameters.buildDirectory) // always throw away changes in the tmpdir!
return false;
const CMakeConfig cache = m_parameters.buildConfiguration->configurationFromCMake();
@@ -375,41 +388,40 @@ bool BuildDirManager::checkConfiguration()
return false; // No cache file yet.
CMakeConfig newConfig;
QSet<QString> changedKeys;
QSet<QString> removedKeys;
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(m_parameters.expander)) {
changedKeys << QString::fromUtf8(iBc.key);
newConfig.append(iCache);
QHash<QString, QPair<QString, QString>> changedKeys;
foreach (const CMakeConfigItem &projectItem, m_parameters.configuration) {
const QString projectKey = QString::fromUtf8(projectItem.key);
const QString projectValue = projectItem.expandedValue(m_parameters.expander);
const CMakeConfigItem &cmakeItem
= Utils::findOrDefault(cache, [&projectItem](const CMakeConfigItem &i) { return i.key == projectItem.key; });
const QString iCacheValue = QString::fromUtf8(cmakeItem.value);
if (cmakeItem.isNull()) {
changedKeys.insert(projectKey, qMakePair(tr("<removed>"), projectValue));
} else if (iCacheValue != projectValue) {
changedKeys.insert(projectKey, qMakePair(iCacheValue, projectValue));
newConfig.append(cmakeItem);
} else {
newConfig.append(iBc);
newConfig.append(projectItem);
}
}
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys;
QStringList keyList = total.toList();
if (!changedKeys.isEmpty()) {
QStringList keyList = changedKeys.keys();
Utils::sort(keyList);
QString table = QLatin1String("<table>");
QString table = QString::fromLatin1("<table><tr><th>%1</th><th>%2</th><th>%3</th></tr>")
.arg(tr("Key")).arg(tr("CMake")).arg(tr("Project"));
foreach (const QString &k, keyList) {
QString change;
if (removedKeys.contains(k))
change = tr("<removed>");
else
change = QString::fromUtf8(CMakeConfigItem::valueOf(k.toUtf8(), cache)).trimmed();
if (change.isEmpty())
change = tr("<empty>");
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td></tr>").arg(k).arg(change.toHtmlEscaped());
const QPair<QString, QString> data = changedKeys.value(k);
table += QString::fromLatin1("\n<tr><td>%1</td><td>%2</td><td>%3</td></tr>")
.arg(k)
.arg(data.first.toHtmlEscaped())
.arg(data.second.toHtmlEscaped());
}
table += QLatin1String("\n</table>");
QPointer<QMessageBox> box = new QMessageBox(Core::ICore::mainWindow());
box->setText(tr("CMake configuration has changed on disk."));
box->setInformativeText(tr("The CMakeCache.txt file has changed: %1").arg(table));
box->setInformativeText(table);
auto *defaultButton = box->addButton(tr("Overwrite Changes in CMake"), QMessageBox::RejectRole);
auto *applyButton = box->addButton(tr("Apply Changes to Project"), QMessageBox::ApplyRole);
box->setDefaultButton(defaultButton);

View File

@@ -40,6 +40,7 @@
#include <functional>
#include <memory>
#include <unordered_map>
namespace ProjectExplorer { class FileNode; }
@@ -112,7 +113,7 @@ private:
void becameDirty();
BuildDirParameters m_parameters;
mutable std::unique_ptr<Utils::TemporaryDirectory> m_tempDir = nullptr;
mutable std::unordered_map<Utils::FileName, std::unique_ptr<Utils::TemporaryDirectory>> m_buildDirToTempDir;
mutable std::unique_ptr<BuildDirReader> m_reader;
mutable bool m_isHandlingError = false;
};

View File

@@ -52,6 +52,7 @@ public:
Utils::FileName sourceDirectory;
Utils::FileName buildDirectory;
Utils::FileName workDirectory; // either buildDirectory or a QTemporaryDirectory!
Utils::Environment environment;
CMakeTool *cmakeTool = nullptr;

View File

@@ -97,7 +97,7 @@ private:
bool isParsing() const;
enum ForceEnabledChanged : quint8 { False, True };
enum ForceEnabledChanged { False, True };
void clearError(ForceEnabledChanged fec = ForceEnabledChanged::False);
void setBuildTargets(const QList<CMakeBuildTarget> &targets);

View File

@@ -177,7 +177,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
m_configView->setUniformRowHeights(true);
m_configView->setSortingEnabled(true);
m_configView->sortByColumn(0, Qt::AscendingOrder);
auto stretcher = new Utils::HeaderViewStretcher(m_configView->header(), 1);
auto stretcher = new Utils::HeaderViewStretcher(m_configView->header(), 0);
m_configView->setSelectionMode(QAbstractItemView::SingleSelection);
m_configView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_configView->setFrameShape(QFrame::NoFrame);
@@ -286,7 +286,7 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_resetButton, &QPushButton::clicked, m_configModel, &ConfigModel::resetAllChanges);
connect(m_reconfigureButton, &QPushButton::clicked, this, [this]() {
m_buildConfiguration->setConfigurationForCMake(m_configModel->configurationChanges());
m_buildConfiguration->setConfigurationForCMake(m_configModel->configurationForCMake());
});
connect(m_unsetButton, &QPushButton::clicked, this, [this]() {
m_configModel->toggleUnsetFlag(mapToSource(m_configView, m_configView->currentIndex()));
@@ -320,7 +320,12 @@ CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeBuildConfiguration *bc)
connect(m_buildConfiguration->target(), &ProjectExplorer::Target::kitChanged,
this, &CMakeBuildSettingsWidget::updateFromKit);
connect(m_buildConfiguration, &CMakeBuildConfiguration::enabledChanged,
this, [this]() { setError(m_buildConfiguration->disabledReason()); });
this, [this]() {
setError(m_buildConfiguration->disabledReason());
setConfigurationForCMake();
});
connect(m_buildConfiguration, &CMakeBuildConfiguration::configurationForCMakeChanged,
this, [this]() { setConfigurationForCMake(); });
updateSelection(QModelIndex(), QModelIndex());
}
@@ -381,7 +386,19 @@ void CMakeBuildSettingsWidget::updateFromKit()
for (const CMakeConfigItem &i : config)
configHash.insert(QString::fromUtf8(i.key), i.expandedValue(k));
m_configModel->setKitConfiguration(configHash);
m_configModel->setConfigurationFromKit(configHash);
}
void CMakeBuildSettingsWidget::setConfigurationForCMake()
{
QHash<QString, QString> config;
const CMakeConfig configList = m_buildConfiguration->configurationForCMake();
for (const CMakeConfigItem &i : configList) {
config.insert(QString::fromUtf8(i.key),
CMakeConfigItem::expandedValueOf(m_buildConfiguration->target()->kit(),
i.key, configList));
}
m_configModel->setConfigurationForCMake(config);
}
void CMakeBuildSettingsWidget::updateSelection(const QModelIndex &current, const QModelIndex &previous)

View File

@@ -65,6 +65,7 @@ private:
void updateAdvancedCheckBox();
void updateFromKit();
void setConfigurationForCMake();
void updateSelection(const QModelIndex &current, const QModelIndex &previous);
QAction *createForceAction(int type, const QModelIndex &idx);

View File

@@ -300,7 +300,7 @@ void CMakeBuildStep::handleProjectWasParsed(QFutureInterface<bool> &fi, bool suc
if (success) {
runImpl(fi);
} else {
AbstractProcessStep::stdError(tr("Project did not parse successfully, can not build."));
AbstractProcessStep::stdError(tr("Project did not parse successfully, cannot build."));
reportRunResult(fi, false);
}
}

View File

@@ -160,11 +160,11 @@ CMakeProject::CMakeProject(const FileName &fileName) : Project(Constants::CMAKEM
return;
// Build configuration has switched:
// * Error out if the reader updates, can not happen since all BCs share a target/kit.
// * Check configuration if reader changes due to it not existing yet:-)
// * run cmake without configuration arguments if the reader stays
m_buildDirManager.setParametersAndRequestParse(
BuildDirParameters(bc),
BuildDirManager::REPARSE_FAIL,
BuildDirManager::REPARSE_CHECK_CONFIGURATION,
BuildDirManager::REPARSE_CHECK_CONFIGURATION);
});

View File

@@ -26,11 +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>

View File

@@ -49,7 +49,7 @@ QByteArray CMakeInputsNode::generateId(const Utils::FileName &inputFile)
bool CMakeInputsNode::showInSimpleTree() const
{
return false;
return true;
}
CMakeListsNode::CMakeListsNode(const Utils::FileName &cmakeListPath) :

View File

@@ -94,13 +94,30 @@ void ConfigModel::setConfiguration(const QList<DataItem> &config)
setConfiguration(Utils::transform(config, [](const DataItem &di) { return InternalDataItem(di); }));
}
void ConfigModel::setKitConfiguration(const QHash<QString, QString> &kitConfig)
void ConfigModel::setConfigurationFromKit(const QHash<QString, QString> &kitConfig)
{
m_kitConfiguration = kitConfig;
for (InternalDataItem &i : m_configuration) {
if (m_kitConfiguration.contains(i.key)) {
if (m_kitConfiguration.contains(i.key))
i.kitValue = m_kitConfiguration.value(i.key);
}
setConfiguration(m_configuration);
}
void ConfigModel::setConfigurationForCMake(const QHash<QString, QString> &config)
{
for (InternalDataItem &i : m_configuration) {
if (!config.contains(i.key))
continue;
const QString v = config.value(i.key);
if (i.value == v) {
i.newValue.clear();
i.isUserChanged = false;
} else {
i.newValue = v;
i.isUserChanged = true;
}
}
setConfiguration(m_configuration);
@@ -202,7 +219,7 @@ ConfigModel::DataItem ConfigModel::dataItemFromIndex(const QModelIndex &idx)
return DataItem();
}
QList<ConfigModel::DataItem> ConfigModel::configurationChanges() const
QList<ConfigModel::DataItem> ConfigModel::configurationForCMake() const
{
const QList<InternalDataItem> tmp
= Utils::filtered(m_configuration, [](const InternalDataItem &i) {
@@ -362,7 +379,7 @@ QString ConfigModel::InternalDataItem::toolTip() const
tooltip << QCoreApplication::translate("CMakeProjectManager", "Not in CMakeCache.txt").arg(value);
}
if (!kitValue.isEmpty())
tooltip << QCoreApplication::translate("CMakeProjectManager::ConfigModel", "Current Kit: %1").arg(kitValue);
tooltip << QCoreApplication::translate("CMakeProjectManager::ConfigModel", "Current kit: %1").arg(kitValue);
return tooltip.join("<br>");
}
@@ -511,7 +528,7 @@ QString ConfigModelTreeItem::toolTip() const
QTC_ASSERT(dataItem, return QString());
QStringList tooltip(dataItem->description);
if (!dataItem->kitValue.isEmpty())
tooltip << QCoreApplication::translate("CMakeProjectManager", "Value requested by Kit: %1").arg(dataItem->kitValue);
tooltip << QCoreApplication::translate("CMakeProjectManager", "Value requested by kit: %1").arg(dataItem->kitValue);
if (dataItem->inCMakeCache) {
if (dataItem->value != dataItem->newValue)
tooltip << QCoreApplication::translate("CMakeProjectManager", "Current CMake: %1").arg(dataItem->value);

View File

@@ -70,7 +70,8 @@ public:
const QStringList &values = QStringList());
void setConfiguration(const CMakeConfig &config);
void setConfiguration(const QList<DataItem> &config);
void setKitConfiguration(const QHash<QString, QString> &kitConfig);
void setConfigurationFromKit(const QHash<QString, QString> &kitConfig);
void setConfigurationForCMake(const QHash<QString, QString> &config);
void flush();
void resetAllChanges();
@@ -84,7 +85,7 @@ public:
static DataItem dataItemFromIndex(const QModelIndex &idx);
QList<DataItem> configurationChanges() const;
QList<DataItem> configurationForCMake() const;
private:

View File

@@ -104,7 +104,7 @@ void ServerModeReader::setParameters(const BuildDirParameters &p)
BuildDirReader::setParameters(p);
if (!m_cmakeServer) {
m_cmakeServer.reset(new ServerMode(p.environment,
p.sourceDirectory, p.buildDirectory,
p.sourceDirectory, p.workDirectory,
p.cmakeTool->cmakeExecutable(),
p.generator, p.extraGenerator, p.platform, p.toolset,
true, 1));
@@ -155,7 +155,7 @@ bool ServerModeReader::isCompatible(const BuildDirParameters &p)
&& p.platform == m_parameters.platform
&& p.toolset == m_parameters.toolset
&& p.sourceDirectory == m_parameters.sourceDirectory
&& p.buildDirectory == m_parameters.buildDirectory;
&& p.workDirectory == m_parameters.workDirectory;
}
void ServerModeReader::resetData()