Commit 5bc0d12c authored by Tobias Hunger's avatar Tobias Hunger

CMake: Check CMakeCache.txt for changes

Check CMakeCache.txt for changes and ask whether to apply these to the
project going forward.

This will only consider settings that were previously changed by Qt Creator
and will not pick up on newly changed settings.

Change-Id: Ia20c67bc2a5e9965243f08003c10ec684875387f
Reviewed-by: default avatarTim Jenssen <tim.jenssen@theqtcompany.com>
parent 8c316aa1
......@@ -30,6 +30,7 @@
#include "cmakeprojectmanager.h"
#include "cmaketool.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <projectexplorer/kit.h>
......@@ -49,6 +50,7 @@
#include <QFile>
#include <QFileInfo>
#include <QFileSystemWatcher>
#include <QMessageBox>
#include <QRegularExpression>
#include <QSet>
#include <QTemporaryDir>
......@@ -91,7 +93,7 @@ static QStringList toArguments(const CMakeConfig &config, const ProjectExplorer:
// BuildDirManager:
// --------------------------------------------------------------------
BuildDirManager::BuildDirManager(const CMakeBuildConfiguration *bc) :
BuildDirManager::BuildDirManager(CMakeBuildConfiguration *bc) :
m_buildConfiguration(bc),
m_watcher(new QFileSystemWatcher(this))
{
......@@ -201,6 +203,8 @@ bool BuildDirManager::persistCMakeState()
void BuildDirManager::parse()
{
checkConfiguration();
CMakeTool *tool = CMakeKitInformation::cmakeTool(kit());
const QString generator = CMakeGeneratorKitInformation::generator(kit());
......@@ -275,6 +279,8 @@ CMakeConfig BuildDirManager::parsedConfiguration() const
if (m_cmakeCache.isEmpty()) {
Utils::FileName cacheFile = workDirectory();
cacheFile.appendPath(QLatin1String("CMakeCache.txt"));
if (!cacheFile.exists())
return m_cmakeCache;
QString errorMessage;
m_cmakeCache = parseConfiguration(cacheFile, &errorMessage);
if (!errorMessage.isEmpty())
......@@ -350,6 +356,7 @@ void BuildDirManager::extractData()
return;
m_watcher->addPath(cbpFile);
m_watcher->addPath(workDirectory().toString() + QLatin1String("/CMakeCache.txt"));
// setFolderName
CMakeCbpParser cbpparser;
......@@ -512,6 +519,61 @@ void BuildDirManager::processCMakeError()
});
}
void BuildDirManager::checkConfiguration()
{
if (m_tempDir) // always throw away changes in the tmpdir!
return;
ProjectExplorer::Kit *k = m_buildConfiguration->target()->kit();
const CMakeConfig cache = parsedConfiguration();
if (cache.isEmpty())
return; // No cache file yet.
CMakeConfig newConfig;
QSet<QString> changedKeys;
QSet<QString> removedKeys;
foreach (const CMakeConfigItem &iBc, intendedConfiguration()) {
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)) {
changedKeys << QString::fromUtf8(iBc.key);
newConfig.append(iCache);
} else {
newConfig.append(iBc);
}
}
if (!changedKeys.isEmpty() || !removedKeys.isEmpty()) {
QSet<QString> total = removedKeys + changedKeys;
QStringList keyList = total.toList();
Utils::sort(keyList);
QString table = QLatin1String("<table>");
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());
}
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->setStandardButtons(QMessageBox::Discard | QMessageBox::Apply);
box->setDefaultButton(QMessageBox::Discard);
int ret = box->exec();
if (ret == QMessageBox::Apply)
m_buildConfiguration->setCMakeConfiguration(newConfig);
}
}
static QByteArray trimCMakeCacheLine(const QByteArray &in) {
int start = 0;
while (start < in.count() && (in.at(start) == ' ' || in.at(start) == '\t'))
......@@ -602,6 +664,8 @@ CMakeConfig BuildDirManager::parseConfiguration(const Utils::FileName &cacheFile
void BuildDirManager::maybeForceReparse()
{
checkConfiguration();
const QByteArray GENERATOR_KEY = "CMAKE_GENERATOR";
const QByteArray EXTRA_GENERATOR_KEY = "CMAKE_EXTRA_GENERATOR";
const QByteArray CMAKE_COMMAND_KEY = "CMAKE_COMMAND";
......
......@@ -63,7 +63,7 @@ class BuildDirManager : public QObject
Q_OBJECT
public:
BuildDirManager(const CMakeBuildConfiguration *bc);
BuildDirManager(CMakeBuildConfiguration *bc);
~BuildDirManager() override;
const ProjectExplorer::Kit *kit() const;
......@@ -87,6 +87,8 @@ public:
void clearFiles();
CMakeConfig parsedConfiguration() const;
void checkConfiguration();
static CMakeConfig parseConfiguration(const Utils::FileName &cacheFile,
QString *errorMessage);
......@@ -106,10 +108,9 @@ private:
void processCMakeOutput();
void processCMakeError();
bool m_hasData = false;
const CMakeBuildConfiguration *m_buildConfiguration = nullptr;
CMakeBuildConfiguration *m_buildConfiguration = nullptr;
Utils::QtcProcess *m_cmakeProcess = nullptr;
QTemporaryDir *m_tempDir = nullptr;
mutable CMakeConfig m_cmakeCache;
......
......@@ -305,8 +305,10 @@ void CMakeProject::runCMake()
return;
BuildDirManager *bdm = bc->buildDirManager();
if (bdm && !bdm->isParsing())
if (bdm && !bdm->isParsing()) {
bdm->checkConfiguration();
bdm->forceReparse();
}
}
QList<CMakeBuildTarget> CMakeProject::buildTargets() const
......
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