From 5bc0d12c6d8b4abdfb7924799866f966880085ef Mon Sep 17 00:00:00 2001 From: Tobias Hunger <tobias.hunger@qt.io> Date: Fri, 13 May 2016 16:19:31 +0200 Subject: [PATCH] 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: Tim Jenssen <tim.jenssen@theqtcompany.com> --- .../cmakeprojectmanager/builddirmanager.cpp | 66 ++++++++++++++++++- .../cmakeprojectmanager/builddirmanager.h | 7 +- .../cmakeprojectmanager/cmakeproject.cpp | 4 +- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.cpp b/src/plugins/cmakeprojectmanager/builddirmanager.cpp index 9ea3fbc472..b717d8aecf 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.cpp +++ b/src/plugins/cmakeprojectmanager/builddirmanager.cpp @@ -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"; diff --git a/src/plugins/cmakeprojectmanager/builddirmanager.h b/src/plugins/cmakeprojectmanager/builddirmanager.h index f88b21580d..419a87c3d1 100644 --- a/src/plugins/cmakeprojectmanager/builddirmanager.h +++ b/src/plugins/cmakeprojectmanager/builddirmanager.h @@ -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; diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp index b7dcd0eaa6..e126a546aa 100644 --- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp @@ -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 -- GitLab