2019-06-13 14:24:04 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** 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 "fileapireader.h"
|
|
|
|
|
|
2022-05-14 02:27:28 +02:00
|
|
|
#include "cmakeprocess.h"
|
2019-06-13 14:24:04 +02:00
|
|
|
#include "fileapidataextractor.h"
|
2020-05-13 12:59:23 +02:00
|
|
|
#include "fileapiparser.h"
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2021-02-04 16:22:40 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
|
|
|
|
|
2019-06-13 14:24:04 +02:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
|
|
|
|
#include <utils/runextensions.h>
|
|
|
|
|
|
|
|
|
|
#include <QLoggingCategory>
|
|
|
|
|
|
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
|
using namespace Utils;
|
|
|
|
|
|
|
|
|
|
namespace CMakeProjectManager {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2020-01-15 14:39:23 +01:00
|
|
|
static Q_LOGGING_CATEGORY(cmakeFileApiMode, "qtc.cmake.fileApiMode", QtWarningMsg);
|
2019-06-13 14:24:04 +02:00
|
|
|
|
|
|
|
|
using namespace FileApiDetails;
|
|
|
|
|
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
// FileApiReader:
|
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
|
|
2020-05-13 12:59:23 +02:00
|
|
|
FileApiReader::FileApiReader()
|
|
|
|
|
: m_lastReplyTimestamp()
|
|
|
|
|
{
|
|
|
|
|
QObject::connect(&m_watcher,
|
|
|
|
|
&FileSystemWatcher::directoryChanged,
|
|
|
|
|
this,
|
|
|
|
|
&FileApiReader::replyDirectoryHasChanged);
|
|
|
|
|
}
|
2019-06-13 14:24:04 +02:00
|
|
|
|
|
|
|
|
FileApiReader::~FileApiReader()
|
|
|
|
|
{
|
|
|
|
|
stop();
|
|
|
|
|
resetData();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileApiReader::setParameters(const BuildDirParameters &p)
|
|
|
|
|
{
|
|
|
|
|
qCDebug(cmakeFileApiMode)
|
|
|
|
|
<< "\n\n\n\n\n=============================================================\n";
|
|
|
|
|
|
|
|
|
|
// Update:
|
|
|
|
|
m_parameters = p;
|
2021-06-09 15:08:13 +02:00
|
|
|
qCDebug(cmakeFileApiMode) << "Work directory:" << m_parameters.buildDirectory.toUserOutput();
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2020-05-13 12:59:23 +02:00
|
|
|
// Reset watcher:
|
2021-09-14 14:36:46 +02:00
|
|
|
m_watcher.clear();
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2021-06-09 15:08:13 +02:00
|
|
|
FileApiParser::setupCMakeFileApi(m_parameters.buildDirectory, m_watcher);
|
2020-05-13 12:59:23 +02:00
|
|
|
|
|
|
|
|
resetData();
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileApiReader::resetData()
|
|
|
|
|
{
|
|
|
|
|
m_cmakeFiles.clear();
|
2021-09-01 19:49:08 +02:00
|
|
|
if (!m_parameters.sourceDirectory.isEmpty()) {
|
|
|
|
|
CMakeFileInfo cmakeListsTxt;
|
|
|
|
|
cmakeListsTxt.path = m_parameters.sourceDirectory.pathAppended("CMakeLists.txt");
|
|
|
|
|
cmakeListsTxt.isCMakeListsDotTxt = true;
|
|
|
|
|
m_cmakeFiles.insert(cmakeListsTxt);
|
|
|
|
|
}
|
2019-06-13 14:24:04 +02:00
|
|
|
|
|
|
|
|
m_cache.clear();
|
|
|
|
|
m_buildTargets.clear();
|
|
|
|
|
m_projectParts.clear();
|
|
|
|
|
m_rootProjectNode.reset();
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-02 14:49:05 +02:00
|
|
|
void FileApiReader::parse(bool forceCMakeRun,
|
|
|
|
|
bool forceInitialConfiguration,
|
|
|
|
|
bool forceExtraConfiguration)
|
2019-06-13 14:24:04 +02:00
|
|
|
{
|
2019-08-09 12:20:49 +02:00
|
|
|
qCDebug(cmakeFileApiMode) << "Parse called with arguments: ForceCMakeRun:" << forceCMakeRun
|
2020-04-02 14:49:05 +02:00
|
|
|
<< " - forceConfiguration:" << forceInitialConfiguration
|
|
|
|
|
<< " - forceExtraConfiguration:" << forceExtraConfiguration;
|
2019-06-13 14:24:04 +02:00
|
|
|
startState();
|
|
|
|
|
|
2020-04-02 14:49:05 +02:00
|
|
|
const QStringList args = (forceInitialConfiguration ? m_parameters.initialCMakeArguments
|
|
|
|
|
: QStringList())
|
2021-12-28 21:42:29 +01:00
|
|
|
+ (forceExtraConfiguration
|
|
|
|
|
? (m_parameters.configurationChangesArguments
|
|
|
|
|
+ m_parameters.additionalCMakeArguments)
|
|
|
|
|
: QStringList());
|
2020-04-02 14:49:05 +02:00
|
|
|
qCDebug(cmakeFileApiMode) << "Parameters request these CMake arguments:" << args;
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2021-06-09 15:08:13 +02:00
|
|
|
const FilePath replyFile = FileApiParser::scanForCMakeReplyFile(m_parameters.buildDirectory);
|
2019-06-21 14:14:31 +02:00
|
|
|
// Only need to update when one of the following conditions is met:
|
2020-04-02 14:49:05 +02:00
|
|
|
// * The user forces the cmake run,
|
|
|
|
|
// * The user provided arguments,
|
2019-06-21 14:14:31 +02:00
|
|
|
// * There is no reply file,
|
|
|
|
|
// * One of the cmakefiles is newer than the replyFile and the user asked
|
|
|
|
|
// for creator to run CMake as needed,
|
2020-05-13 12:24:59 +02:00
|
|
|
// * A query file is newer than the reply file
|
2020-04-02 14:49:05 +02:00
|
|
|
const bool hasArguments = !args.isEmpty();
|
2021-06-08 14:42:59 +02:00
|
|
|
const bool replyFileMissing = !replyFile.exists();
|
2020-04-02 14:49:05 +02:00
|
|
|
const bool cmakeFilesChanged = m_parameters.cmakeTool() && m_parameters.cmakeTool()->isAutoRun()
|
2021-09-01 19:49:08 +02:00
|
|
|
&& anyOf(m_cmakeFiles, [&replyFile](const CMakeFileInfo &info) {
|
|
|
|
|
return !info.isGenerated
|
|
|
|
|
&& info.path.lastModified() > replyFile.lastModified();
|
2020-04-02 14:49:05 +02:00
|
|
|
});
|
2021-06-09 15:08:13 +02:00
|
|
|
const bool queryFileChanged = anyOf(FileApiParser::cmakeQueryFilePaths(m_parameters.buildDirectory),
|
2021-06-08 14:42:59 +02:00
|
|
|
[&replyFile](const FilePath &qf) {
|
|
|
|
|
return qf.lastModified() > replyFile.lastModified();
|
2020-04-02 14:49:05 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const bool mustUpdate = forceCMakeRun || hasArguments || replyFileMissing || cmakeFilesChanged
|
|
|
|
|
|| queryFileChanged;
|
|
|
|
|
qCDebug(cmakeFileApiMode) << QString("Do I need to run CMake? %1 "
|
|
|
|
|
"(force: %2 | args: %3 | missing reply: %4 | "
|
|
|
|
|
"cmakeFilesChanged: %5 | "
|
|
|
|
|
"queryFileChanged: %6)")
|
|
|
|
|
.arg(mustUpdate)
|
|
|
|
|
.arg(forceCMakeRun)
|
|
|
|
|
.arg(hasArguments)
|
|
|
|
|
.arg(replyFileMissing)
|
|
|
|
|
.arg(cmakeFilesChanged)
|
|
|
|
|
.arg(queryFileChanged);
|
2019-06-13 14:24:04 +02:00
|
|
|
|
|
|
|
|
if (mustUpdate) {
|
2020-04-02 14:49:05 +02:00
|
|
|
qCDebug(cmakeFileApiMode) << QString("FileApiReader: Starting CMake with \"%1\".")
|
|
|
|
|
.arg(args.join("\", \""));
|
|
|
|
|
startCMakeState(args);
|
|
|
|
|
} else {
|
2021-09-21 22:22:37 +02:00
|
|
|
endState(replyFile, false);
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileApiReader::stop()
|
|
|
|
|
{
|
2020-04-24 10:29:43 +02:00
|
|
|
if (m_cmakeProcess)
|
|
|
|
|
disconnect(m_cmakeProcess.get(), nullptr, this, nullptr);
|
2019-06-13 14:24:04 +02:00
|
|
|
m_cmakeProcess.reset();
|
2021-05-31 13:38:41 +02:00
|
|
|
|
|
|
|
|
if (m_future) {
|
|
|
|
|
m_future->cancel();
|
|
|
|
|
m_future->waitForFinished();
|
|
|
|
|
}
|
|
|
|
|
m_future = {};
|
|
|
|
|
m_isParsing = false;
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-22 15:18:00 +01:00
|
|
|
void FileApiReader::stopCMakeRun()
|
|
|
|
|
{
|
|
|
|
|
if (m_cmakeProcess)
|
2022-05-13 18:22:03 +02:00
|
|
|
m_cmakeProcess->stop();
|
2021-12-22 15:18:00 +01:00
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:24:04 +02:00
|
|
|
bool FileApiReader::isParsing() const
|
|
|
|
|
{
|
|
|
|
|
return m_isParsing;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-02 18:34:12 +01:00
|
|
|
QSet<FilePath> FileApiReader::projectFilesToWatch() const
|
2019-08-15 12:22:09 +02:00
|
|
|
{
|
2021-09-01 19:49:08 +02:00
|
|
|
return Utils::transform(
|
|
|
|
|
Utils::filtered(m_cmakeFiles,
|
|
|
|
|
[](const CMakeFileInfo &info) { return !info.isGenerated; }),
|
|
|
|
|
[](const CMakeFileInfo &info) { return info.path;});
|
2019-08-15 12:22:09 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:24:04 +02:00
|
|
|
QList<CMakeBuildTarget> FileApiReader::takeBuildTargets(QString &errorMessage){
|
|
|
|
|
Q_UNUSED(errorMessage)
|
|
|
|
|
|
2021-06-08 18:06:40 +02:00
|
|
|
return std::exchange(m_buildTargets, {});
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CMakeConfig FileApiReader::takeParsedConfiguration(QString &errorMessage)
|
|
|
|
|
{
|
2021-02-04 16:22:40 +01:00
|
|
|
if (m_lastCMakeExitCode != 0)
|
|
|
|
|
errorMessage = tr("CMake returned error code: %1").arg(m_lastCMakeExitCode);
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2021-06-08 18:06:40 +02:00
|
|
|
return std::exchange(m_cache, {});
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-28 15:10:04 +02:00
|
|
|
QString FileApiReader::ctestPath() const
|
|
|
|
|
{
|
|
|
|
|
// if we failed to run cmake we should not offer ctest information either
|
|
|
|
|
return m_lastCMakeExitCode == 0 ? m_ctestPath : QString();
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-14 16:38:55 +01:00
|
|
|
bool FileApiReader::isMultiConfig() const
|
|
|
|
|
{
|
|
|
|
|
return m_isMultiConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FileApiReader::usesAllCapsTargets() const
|
|
|
|
|
{
|
|
|
|
|
return m_usesAllCapsTargets;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-28 18:22:45 +02:00
|
|
|
RawProjectParts FileApiReader::createRawProjectParts(QString &errorMessage)
|
2019-06-13 14:24:04 +02:00
|
|
|
{
|
|
|
|
|
Q_UNUSED(errorMessage)
|
|
|
|
|
|
2021-06-08 18:06:40 +02:00
|
|
|
return std::exchange(m_projectParts, {});
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileApiReader::startState()
|
|
|
|
|
{
|
|
|
|
|
qCDebug(cmakeFileApiMode) << "FileApiReader: START STATE.";
|
|
|
|
|
QTC_ASSERT(!m_isParsing, return );
|
|
|
|
|
QTC_ASSERT(!m_future.has_value(), return );
|
|
|
|
|
|
|
|
|
|
m_isParsing = true;
|
|
|
|
|
|
|
|
|
|
qCDebug(cmakeFileApiMode) << "FileApiReader: CONFIGURATION STARTED SIGNAL";
|
|
|
|
|
emit configurationStarted();
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-21 22:22:37 +02:00
|
|
|
void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBackup)
|
2019-06-13 14:24:04 +02:00
|
|
|
{
|
|
|
|
|
qCDebug(cmakeFileApiMode) << "FileApiReader: END STATE.";
|
|
|
|
|
QTC_ASSERT(m_isParsing, return );
|
|
|
|
|
QTC_ASSERT(!m_future.has_value(), return );
|
|
|
|
|
|
|
|
|
|
const FilePath sourceDirectory = m_parameters.sourceDirectory;
|
2021-06-09 15:08:13 +02:00
|
|
|
const FilePath buildDirectory = m_parameters.buildDirectory;
|
2021-03-03 16:06:20 +01:00
|
|
|
const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType;
|
2019-06-13 14:24:04 +02:00
|
|
|
|
2021-06-08 14:42:59 +02:00
|
|
|
QTC_CHECK(!replyFilePath.needsDevice());
|
|
|
|
|
m_lastReplyTimestamp = replyFilePath.lastModified();
|
2019-07-25 15:16:55 +02:00
|
|
|
|
2019-06-13 14:24:04 +02:00
|
|
|
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
|
2021-09-27 17:26:40 +02:00
|
|
|
[replyFilePath, sourceDirectory, buildDirectory, cmakeBuildType](
|
2021-05-31 15:09:28 +02:00
|
|
|
QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) {
|
2021-05-31 13:38:41 +02:00
|
|
|
auto result = std::make_shared<FileApiQtcData>();
|
2021-05-31 15:09:28 +02:00
|
|
|
FileApiData data = FileApiParser::parseData(fi,
|
2021-06-08 14:42:59 +02:00
|
|
|
replyFilePath,
|
2021-05-31 15:09:28 +02:00
|
|
|
cmakeBuildType,
|
|
|
|
|
result->errorMessage);
|
2021-09-27 17:26:40 +02:00
|
|
|
if (result->errorMessage.isEmpty())
|
2020-10-26 15:36:59 +01:00
|
|
|
*result = extractData(data, sourceDirectory, buildDirectory);
|
2021-09-27 17:26:40 +02:00
|
|
|
else
|
2019-06-13 14:24:04 +02:00
|
|
|
qWarning() << result->errorMessage;
|
|
|
|
|
|
2021-05-31 15:09:28 +02:00
|
|
|
fi.reportResult(result);
|
2019-06-13 14:24:04 +02:00
|
|
|
});
|
2021-05-31 13:38:41 +02:00
|
|
|
onResultReady(m_future.value(),
|
|
|
|
|
this,
|
2021-09-27 17:26:40 +02:00
|
|
|
[this, sourceDirectory, buildDirectory, restoredFromBackup](
|
2021-05-31 13:38:41 +02:00
|
|
|
const std::shared_ptr<FileApiQtcData> &value) {
|
|
|
|
|
m_isParsing = false;
|
|
|
|
|
m_cache = std::move(value->cache);
|
|
|
|
|
m_cmakeFiles = std::move(value->cmakeFiles);
|
|
|
|
|
m_buildTargets = std::move(value->buildTargets);
|
|
|
|
|
m_projectParts = std::move(value->projectParts);
|
|
|
|
|
m_rootProjectNode = std::move(value->rootProjectNode);
|
|
|
|
|
m_ctestPath = std::move(value->ctestPath);
|
|
|
|
|
m_isMultiConfig = std::move(value->isMultiConfig);
|
|
|
|
|
m_usesAllCapsTargets = std::move(value->usesAllCapsTargets);
|
|
|
|
|
|
|
|
|
|
if (value->errorMessage.isEmpty()) {
|
2021-09-21 22:22:37 +02:00
|
|
|
emit this->dataAvailable(restoredFromBackup);
|
2021-05-31 13:38:41 +02:00
|
|
|
} else {
|
|
|
|
|
emit this->errorOccurred(value->errorMessage);
|
|
|
|
|
}
|
|
|
|
|
m_future = {};
|
|
|
|
|
});
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
2021-02-04 16:22:40 +01:00
|
|
|
void FileApiReader::makeBackupConfiguration(bool store)
|
|
|
|
|
{
|
2021-06-09 15:08:13 +02:00
|
|
|
FilePath reply = m_parameters.buildDirectory.pathAppended(".cmake/api/v1/reply");
|
|
|
|
|
FilePath replyPrev = m_parameters.buildDirectory.pathAppended(".cmake/api/v1/reply.prev");
|
2021-02-04 16:22:40 +01:00
|
|
|
if (!store)
|
|
|
|
|
std::swap(reply, replyPrev);
|
|
|
|
|
|
|
|
|
|
if (reply.exists()) {
|
|
|
|
|
if (replyPrev.exists())
|
2021-06-28 15:26:44 +02:00
|
|
|
replyPrev.removeRecursively();
|
|
|
|
|
QTC_CHECK(!replyPrev.exists());
|
2021-06-28 13:57:10 +02:00
|
|
|
if (!reply.renameFile(replyPrev))
|
2021-02-04 16:22:40 +01:00
|
|
|
Core::MessageManager::writeFlashing(tr("Failed to rename %1 to %2.")
|
|
|
|
|
.arg(reply.toString(), replyPrev.toString()));
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-09 15:08:13 +02:00
|
|
|
FilePath cmakeCacheTxt = m_parameters.buildDirectory.pathAppended("CMakeCache.txt");
|
|
|
|
|
FilePath cmakeCacheTxtPrev = m_parameters.buildDirectory.pathAppended("CMakeCache.txt.prev");
|
2021-02-04 16:22:40 +01:00
|
|
|
if (!store)
|
|
|
|
|
std::swap(cmakeCacheTxt, cmakeCacheTxtPrev);
|
|
|
|
|
|
2021-03-05 11:32:47 +01:00
|
|
|
if (cmakeCacheTxt.exists())
|
|
|
|
|
if (!FileUtils::copyIfDifferent(cmakeCacheTxt, cmakeCacheTxtPrev))
|
|
|
|
|
Core::MessageManager::writeFlashing(tr("Failed to copy %1 to %2.")
|
|
|
|
|
.arg(cmakeCacheTxt.toString(), cmakeCacheTxtPrev.toString()));
|
2021-02-04 16:22:40 +01:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-28 12:02:18 +02:00
|
|
|
void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &configurationArguments)
|
|
|
|
|
{
|
2021-06-09 15:08:13 +02:00
|
|
|
const FilePath buildDir = m_parameters.buildDirectory;
|
2021-06-16 09:06:34 +02:00
|
|
|
QTC_CHECK(buildDir.ensureWritableDir());
|
2021-05-28 12:02:18 +02:00
|
|
|
|
|
|
|
|
QByteArray contents;
|
2022-02-03 11:24:56 +01:00
|
|
|
QStringList unknownOptions;
|
2021-05-28 12:02:18 +02:00
|
|
|
contents.append("# This file is managed by Qt Creator, do not edit!\n\n");
|
|
|
|
|
contents.append(
|
2022-02-03 11:24:56 +01:00
|
|
|
transform(CMakeConfig::fromArguments(configurationArguments, unknownOptions).toList(),
|
2021-12-28 21:42:29 +01:00
|
|
|
[](const CMakeConfigItem &item) { return item.toCMakeSetLine(nullptr); })
|
2021-05-28 12:02:18 +02:00
|
|
|
.join('\n')
|
|
|
|
|
.toUtf8());
|
|
|
|
|
|
2021-06-16 09:06:34 +02:00
|
|
|
const FilePath settingsFile = buildDir / "qtcsettings.cmake";
|
|
|
|
|
QTC_CHECK(settingsFile.writeFileContents(contents));
|
2021-05-28 12:02:18 +02:00
|
|
|
}
|
|
|
|
|
|
2021-09-27 17:26:40 +02:00
|
|
|
std::unique_ptr<CMakeProjectNode> FileApiReader::rootProjectNode()
|
|
|
|
|
{
|
|
|
|
|
return std::exchange(m_rootProjectNode, {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FilePath FileApiReader::topCmakeFile() const
|
|
|
|
|
{
|
|
|
|
|
return m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{};
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-21 22:22:37 +02:00
|
|
|
int FileApiReader::lastCMakeExitCode() const
|
|
|
|
|
{
|
|
|
|
|
return m_lastCMakeExitCode;
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-13 14:24:04 +02:00
|
|
|
void FileApiReader::startCMakeState(const QStringList &configurationArguments)
|
|
|
|
|
{
|
|
|
|
|
qCDebug(cmakeFileApiMode) << "FileApiReader: START CMAKE STATE.";
|
|
|
|
|
QTC_ASSERT(!m_cmakeProcess, return );
|
|
|
|
|
|
|
|
|
|
m_cmakeProcess = std::make_unique<CMakeProcess>();
|
|
|
|
|
|
|
|
|
|
connect(m_cmakeProcess.get(), &CMakeProcess::finished, this, &FileApiReader::cmakeFinishedState);
|
|
|
|
|
|
|
|
|
|
qCDebug(cmakeFileApiMode) << ">>>>>> Running cmake with arguments:" << configurationArguments;
|
2021-06-08 10:27:53 +02:00
|
|
|
// Reset watcher:
|
|
|
|
|
m_watcher.removeFiles(m_watcher.files());
|
|
|
|
|
m_watcher.removeDirectories(m_watcher.directories());
|
|
|
|
|
|
2021-02-04 16:22:40 +01:00
|
|
|
makeBackupConfiguration(true);
|
2021-05-28 12:02:18 +02:00
|
|
|
writeConfigurationIntoBuildDirectory(configurationArguments);
|
2019-06-13 14:24:04 +02:00
|
|
|
m_cmakeProcess->run(m_parameters, configurationArguments);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-08 13:40:45 +02:00
|
|
|
void FileApiReader::cmakeFinishedState()
|
2019-06-13 14:24:04 +02:00
|
|
|
{
|
|
|
|
|
qCDebug(cmakeFileApiMode) << "FileApiReader: CMAKE FINISHED STATE.";
|
|
|
|
|
|
2020-09-28 15:10:04 +02:00
|
|
|
m_lastCMakeExitCode = m_cmakeProcess->lastExitCode();
|
2019-10-08 12:45:06 +02:00
|
|
|
m_cmakeProcess.release()->deleteLater();
|
|
|
|
|
|
2021-02-04 16:22:40 +01:00
|
|
|
if (m_lastCMakeExitCode != 0)
|
|
|
|
|
makeBackupConfiguration(false);
|
|
|
|
|
|
2021-06-09 15:08:13 +02:00
|
|
|
FileApiParser::setupCMakeFileApi(m_parameters.buildDirectory, m_watcher);
|
2021-06-08 10:27:53 +02:00
|
|
|
|
2021-09-21 22:22:37 +02:00
|
|
|
endState(FileApiParser::scanForCMakeReplyFile(m_parameters.buildDirectory),
|
|
|
|
|
m_lastCMakeExitCode != 0);
|
2020-05-13 12:59:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileApiReader::replyDirectoryHasChanged(const QString &directory) const
|
|
|
|
|
{
|
|
|
|
|
if (m_isParsing)
|
|
|
|
|
return; // This has been triggered by ourselves, ignore.
|
|
|
|
|
|
2021-06-09 15:08:13 +02:00
|
|
|
const FilePath reply = FileApiParser::scanForCMakeReplyFile(m_parameters.buildDirectory);
|
2021-06-08 14:42:59 +02:00
|
|
|
const FilePath dir = reply.absolutePath();
|
2020-05-13 12:59:23 +02:00
|
|
|
if (dir.isEmpty())
|
|
|
|
|
return; // CMake started to fill the result dir, but has not written a result file yet
|
2021-06-08 14:42:59 +02:00
|
|
|
QTC_CHECK(!dir.needsDevice());
|
|
|
|
|
QTC_ASSERT(dir.path() == directory, return);
|
2020-05-13 12:59:23 +02:00
|
|
|
|
2021-06-08 14:42:59 +02:00
|
|
|
if (m_lastReplyTimestamp.isValid() && reply.lastModified() > m_lastReplyTimestamp)
|
2020-05-13 12:59:23 +02:00
|
|
|
emit dirty();
|
2019-06-13 14:24:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace CMakeProjectManager
|