CMakePM: Scan files only on CMake configuration failure

The file tree scanner will only be started on CMake configuration
failure to generate the <File System> fall back project node.

Change-Id: I873ef1189fd43dc9bffa03aeafabb00bb3b8b6af
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Cristian Adam
2021-09-27 17:26:40 +02:00
parent b8609be931
commit 0665a9151c
6 changed files with 83 additions and 123 deletions

View File

@@ -35,6 +35,7 @@
#include "cmakeprojectnodes.h" #include "cmakeprojectnodes.h"
#include "cmakeprojectplugin.h" #include "cmakeprojectplugin.h"
#include "cmakespecificsettings.h" #include "cmakespecificsettings.h"
#include "projecttreehelper.h"
#include "utils/algorithm.h" #include "utils/algorithm.h"
#include <android/androidconstants.h> #include <android/androidconstants.h>
@@ -158,8 +159,7 @@ CMakeBuildSystem::CMakeBuildSystem(CMakeBuildConfiguration *bc)
m_treeScanner.setFilter([this](const MimeType &mimeType, const FilePath &fn) { m_treeScanner.setFilter([this](const MimeType &mimeType, const FilePath &fn) {
// Mime checks requires more resources, so keep it last in check list // Mime checks requires more resources, so keep it last in check list
auto isIgnored = fn.toString().startsWith(projectFilePath().toString() + ".user") auto isIgnored = TreeScanner::isWellKnownBinary(mimeType, fn);
|| TreeScanner::isWellKnownBinary(mimeType, fn);
// Cache mime check result for speed up // Cache mime check result for speed up
if (!isIgnored) { if (!isIgnored) {
@@ -213,7 +213,6 @@ CMakeBuildSystem::~CMakeBuildSystem()
delete m_cppCodeModelUpdater; delete m_cppCodeModelUpdater;
qDeleteAll(m_extraCompilers); qDeleteAll(m_extraCompilers);
qDeleteAll(m_allFiles.allFiles);
} }
void CMakeBuildSystem::triggerParsing() void CMakeBuildSystem::triggerParsing()
@@ -244,28 +243,11 @@ void CMakeBuildSystem::triggerParsing()
qCDebug(cmakeBuildSystemLog) << "ParseGuard acquired."; qCDebug(cmakeBuildSystemLog) << "ParseGuard acquired.";
if (m_allFiles.allFiles.isEmpty()) {
qCDebug(cmakeBuildSystemLog)
<< "No treescanner information available, forcing treescanner run.";
updateReparseParameters(REPARSE_SCAN);
}
int reparseParameters = takeReparseParameters(); int reparseParameters = takeReparseParameters();
m_waitingForScan = (reparseParameters & REPARSE_SCAN) != 0;
m_waitingForParse = true; m_waitingForParse = true;
m_combinedScanAndParseResult = true; m_combinedScanAndParseResult = true;
if (m_waitingForScan) {
qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner";
QTC_CHECK(m_treeScanner.isFinished());
if (m_treeScanner.asyncScanForFiles(projectDirectory()))
Core::ProgressManager::addTask(m_treeScanner.future(),
tr("Scan \"%1\" project tree")
.arg(project()->displayName()),
"CMake.Scan.Tree");
}
QTC_ASSERT(m_parameters.isValid(), return ); QTC_ASSERT(m_parameters.isValid(), return );
TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM); TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
@@ -365,8 +347,6 @@ QString CMakeBuildSystem::reparseParametersString(int reparseFlags)
result += " FORCE_CMAKE_RUN"; result += " FORCE_CMAKE_RUN";
if (reparseFlags & REPARSE_FORCE_INITIAL_CONFIGURATION) if (reparseFlags & REPARSE_FORCE_INITIAL_CONFIGURATION)
result += " FORCE_CONFIG"; result += " FORCE_CONFIG";
if (reparseFlags & REPARSE_SCAN)
result += " SCAN";
} }
return result.trimmed(); return result.trimmed();
} }
@@ -442,7 +422,7 @@ void CMakeBuildSystem::runCMakeAndScanProjectTree()
BuildDirParameters parameters(cmakeBuildConfiguration()); BuildDirParameters parameters(cmakeBuildConfiguration());
qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command"; qCDebug(cmakeBuildSystemLog) << "Requesting parse due to \"Rescan Project\" command";
setParametersAndRequestParse(parameters, setParametersAndRequestParse(parameters,
REPARSE_FORCE_CMAKE_RUN | REPARSE_SCAN | REPARSE_URGENT); REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT);
} }
void CMakeBuildSystem::runCMakeWithExtraArguments() void CMakeBuildSystem::runCMakeWithExtraArguments()
@@ -461,18 +441,6 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget)
cmakeBuildConfiguration()->buildTarget(buildTarget); cmakeBuildConfiguration()->buildTarget(buildTarget);
} }
void CMakeBuildSystem::handleTreeScanningFinished()
{
QTC_CHECK(m_waitingForScan);
qDeleteAll(m_allFiles.allFiles);
m_allFiles = m_treeScanner.release();
m_waitingForScan = false;
combineScanAndParse(m_reader.lastCMakeExitCode() != 0);
}
bool CMakeBuildSystem::persistCMakeState() bool CMakeBuildSystem::persistCMakeState()
{ {
BuildDirParameters parameters(cmakeBuildConfiguration()); BuildDirParameters parameters(cmakeBuildConfiguration());
@@ -524,17 +492,10 @@ void CMakeBuildSystem::clearCMakeCache()
path.removeRecursively(); path.removeRecursively();
} }
std::unique_ptr<CMakeProjectNode> CMakeBuildSystem::generateProjectTree(
const TreeScanner::Result &allFiles, bool failedToParse)
{
auto root = m_reader.generateProjectTree(allFiles, failedToParse);
return root;
}
void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup) void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
{ {
if (cmakeBuildConfiguration()->isActive()) { if (cmakeBuildConfiguration()->isActive()) {
if (m_waitingForParse || m_waitingForScan) if (m_waitingForParse)
return; return;
if (m_combinedScanAndParseResult) { if (m_combinedScanAndParseResult) {
@@ -548,6 +509,15 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
"<p>The backup of the previous configuration has been restored.</p>" "<p>The backup of the previous configuration has been restored.</p>"
"<p>Have a look at the Issues pane or in the \"Projects > Build\" settings " "<p>Have a look at the Issues pane or in the \"Projects > Build\" settings "
"for more information about the failure.</p")); "for more information about the failure.</p"));
m_reader.resetData();
m_currentGuard = {};
m_testNames.clear();
emitBuildSystemUpdated();
runCTest();
} else { } else {
updateFallbackProjectData(); updateFallbackProjectData();
@@ -558,15 +528,6 @@ void CMakeBuildSystem::combineScanAndParse(bool restoredFromBackup)
"for more information about the failure.</p")); "for more information about the failure.</p"));
} }
} }
m_reader.resetData();
m_currentGuard = {};
m_testNames.clear();
emitBuildSystemUpdated();
runCTest();
} }
void CMakeBuildSystem::checkAndReportError(QString &errorMessage) void CMakeBuildSystem::checkAndReportError(QString &errorMessage)
@@ -614,7 +575,7 @@ void CMakeBuildSystem::updateProjectData()
Project *p = project(); Project *p = project();
{ {
auto newRoot = generateProjectTree(m_allFiles, false); auto newRoot = m_reader.rootProjectNode();
if (newRoot) { if (newRoot) {
setRootProjectNode(std::move(newRoot)); setRootProjectNode(std::move(newRoot));
@@ -707,16 +668,51 @@ void CMakeBuildSystem::updateProjectData()
qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date."; qCDebug(cmakeBuildSystemLog) << "All CMake project data up to date.";
} }
void CMakeBuildSystem::handleTreeScanningFinished()
{
TreeScanner::Result result = m_treeScanner.release();
m_allFiles = result.folderNode;
qDeleteAll(result.allFiles);
updateFileSystemNodes();
}
void CMakeBuildSystem::updateFileSystemNodes()
{
auto newRoot = std::make_unique<CMakeProjectNode>(m_parameters.sourceDirectory);
newRoot->setDisplayName(m_parameters.sourceDirectory.fileName());
if (!m_reader.topCmakeFile().isEmpty()) {
auto node = std::make_unique<FileNode>(m_reader.topCmakeFile(), FileType::Project);
node->setIsGenerated(false);
std::vector<std::unique_ptr<FileNode>> fileNodes;
fileNodes.emplace_back(std::move(node));
addCMakeLists(newRoot.get(), std::move(fileNodes));
}
addFileSystemNodes(newRoot.get(), m_allFiles);
setRootProjectNode(std::move(newRoot));
m_reader.resetData();
m_currentGuard = {};
emitBuildSystemUpdated();
qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date.";
}
void CMakeBuildSystem::updateFallbackProjectData() void CMakeBuildSystem::updateFallbackProjectData()
{ {
qCDebug(cmakeBuildSystemLog) << "Updating fallback CMake project data"; qCDebug(cmakeBuildSystemLog) << "Updating fallback CMake project data";
qCDebug(cmakeBuildSystemLog) << "Starting TreeScanner";
QTC_ASSERT(m_treeScanner.isFinished() && !m_reader.isParsing(), return ); QTC_CHECK(m_treeScanner.isFinished());
if (m_treeScanner.asyncScanForFiles(projectDirectory()))
auto newRoot = generateProjectTree(m_allFiles, true); Core::ProgressManager::addTask(m_treeScanner.future(),
setRootProjectNode(std::move(newRoot)); tr("Scan \"%1\" project tree")
.arg(project()->displayName()),
qCDebug(cmakeBuildSystemLog) << "All fallback CMake project data up to date."; "CMake.Scan.Tree");
} }
void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage) void CMakeBuildSystem::updateCMakeConfiguration(QString &errorMessage)
@@ -899,7 +895,7 @@ void CMakeBuildSystem::becameDirty()
if (isParsing()) if (isParsing())
return; return;
setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_SCAN); setParametersAndRequestParse(BuildDirParameters(cmakeBuildConfiguration()), REPARSE_DEFAULT);
} }
void CMakeBuildSystem::updateReparseParameters(const int parameters) void CMakeBuildSystem::updateReparseParameters(const int parameters)

View File

@@ -37,7 +37,10 @@
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
namespace CppEditor { class CppProjectUpdater; } namespace CppEditor { class CppProjectUpdater; }
namespace ProjectExplorer { class ExtraCompiler; } namespace ProjectExplorer {
class ExtraCompiler;
class FolderNode;
}
namespace CMakeProjectManager { namespace CMakeProjectManager {
@@ -113,8 +116,7 @@ private:
REPARSE_FORCE_INITIAL_CONFIGURATION REPARSE_FORCE_INITIAL_CONFIGURATION
= (1 << 1), // Force initial configuration arguments to cmake = (1 << 1), // Force initial configuration arguments to cmake
REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake
REPARSE_SCAN = (1 << 3), // Run filesystem scan REPARSE_URGENT = (1 << 3), // Do not delay the parser run by 1s
REPARSE_URGENT = (1 << 4), // Do not delay the parser run by 1s
}; };
QString reparseParametersString(int reparseFlags); QString reparseParametersString(int reparseFlags);
void setParametersAndRequestParse(const BuildDirParameters &parameters, void setParametersAndRequestParse(const BuildDirParameters &parameters,
@@ -132,9 +134,6 @@ private:
// Combining Treescanner and Parser states: // Combining Treescanner and Parser states:
void combineScanAndParse(bool restoredFromBackup); void combineScanAndParse(bool restoredFromBackup);
std::unique_ptr<CMakeProjectNode> generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse);
void checkAndReportError(QString &errorMessage); void checkAndReportError(QString &errorMessage);
void updateCMakeConfiguration(QString &errorMessage); void updateCMakeConfiguration(QString &errorMessage);
@@ -146,6 +145,8 @@ private:
const QList<QByteArray> &moduleMappings); const QList<QByteArray> &moduleMappings);
void updateInitialCMakeExpandableVars(); void updateInitialCMakeExpandableVars();
void updateFileSystemNodes();
void handleParsingSucceeded(bool restoredFromBackup); void handleParsingSucceeded(bool restoredFromBackup);
void handleParsingFailed(const QString &msg); void handleParsingFailed(const QString &msg);
@@ -161,10 +162,9 @@ private:
void runCTest(); void runCTest();
ProjectExplorer::TreeScanner m_treeScanner; ProjectExplorer::TreeScanner m_treeScanner;
ProjectExplorer::TreeScanner::Result m_allFiles; std::shared_ptr<ProjectExplorer::FolderNode> m_allFiles;
QHash<QString, bool> m_mimeBinaryCache; QHash<QString, bool> m_mimeBinaryCache;
bool m_waitingForScan = false;
bool m_waitingForParse = false; bool m_waitingForParse = false;
bool m_combinedScanAndParseResult = false; bool m_combinedScanAndParseResult = false;

View File

@@ -721,31 +721,5 @@ FileApiQtcData extractData(FileApiData &input,
return result; return result;
} }
FileApiQtcData generateFallbackData(const FilePath &topCmakeFile,
const FilePath &sourceDirectory,
const FilePath &buildDirectory,
QString errorMessage)
{
Q_UNUSED(buildDirectory)
FileApiQtcData result;
result.rootProjectNode.reset(new CMakeProjectNode{sourceDirectory});
result.rootProjectNode->setDisplayName(sourceDirectory.fileName());
result.errorMessage = errorMessage;
if (!topCmakeFile.isEmpty()) {
auto node = std::make_unique<FileNode>(topCmakeFile, FileType::Project);
node->setIsGenerated(false);
std::vector<std::unique_ptr<FileNode>> fileNodes;
fileNodes.emplace_back(std::move(node));
addCMakeLists(result.rootProjectNode.get(), std::move(fileNodes));
}
return result;
}
} // namespace Internal } // namespace Internal
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

@@ -75,10 +75,6 @@ public:
FileApiQtcData extractData(FileApiData &data, FileApiQtcData extractData(FileApiData &data,
const Utils::FilePath &sourceDirectory, const Utils::FilePath &sourceDirectory,
const Utils::FilePath &buildDirectory); const Utils::FilePath &buildDirectory);
FileApiQtcData generateFallbackData(const Utils::FilePath &topCmakeFile,
const Utils::FilePath &sourceDirectory,
const Utils::FilePath &buildDirectory,
QString errorMessage);
} // namespace Internal } // namespace Internal
} // namespace CMakeProjectManager } // namespace CMakeProjectManager

View File

@@ -27,7 +27,6 @@
#include "fileapidataextractor.h" #include "fileapidataextractor.h"
#include "fileapiparser.h" #include "fileapiparser.h"
#include "projecttreehelper.h"
#include <coreplugin/messagemanager.h> #include <coreplugin/messagemanager.h>
@@ -214,15 +213,6 @@ bool FileApiReader::usesAllCapsTargets() const
return m_usesAllCapsTargets; return m_usesAllCapsTargets;
} }
std::unique_ptr<CMakeProjectNode> FileApiReader::generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse)
{
if (failedToParse)
addFileSystemNodes(m_rootProjectNode.get(), allFiles.folderNode);
return std::exchange(m_rootProjectNode, {});
}
RawProjectParts FileApiReader::createRawProjectParts(QString &errorMessage) RawProjectParts FileApiReader::createRawProjectParts(QString &errorMessage)
{ {
Q_UNUSED(errorMessage) Q_UNUSED(errorMessage)
@@ -250,37 +240,29 @@ void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBac
const FilePath sourceDirectory = m_parameters.sourceDirectory; const FilePath sourceDirectory = m_parameters.sourceDirectory;
const FilePath buildDirectory = m_parameters.buildDirectory; const FilePath buildDirectory = m_parameters.buildDirectory;
const FilePath topCmakeFile = m_cmakeFiles.size() == 1 ? (*m_cmakeFiles.begin()).path : FilePath{};
const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType; const QString cmakeBuildType = m_parameters.cmakeBuildType == "Build" ? "" : m_parameters.cmakeBuildType;
QTC_CHECK(!replyFilePath.needsDevice()); QTC_CHECK(!replyFilePath.needsDevice());
m_lastReplyTimestamp = replyFilePath.lastModified(); m_lastReplyTimestamp = replyFilePath.lastModified();
m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(), m_future = runAsync(ProjectExplorerPlugin::sharedThreadPool(),
[replyFilePath, sourceDirectory, buildDirectory, topCmakeFile, cmakeBuildType]( [replyFilePath, sourceDirectory, buildDirectory, cmakeBuildType](
QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) { QFutureInterface<std::shared_ptr<FileApiQtcData>> &fi) {
auto result = std::make_shared<FileApiQtcData>(); auto result = std::make_shared<FileApiQtcData>();
FileApiData data = FileApiParser::parseData(fi, FileApiData data = FileApiParser::parseData(fi,
replyFilePath, replyFilePath,
cmakeBuildType, cmakeBuildType,
result->errorMessage); result->errorMessage);
if (!result->errorMessage.isEmpty()) { if (result->errorMessage.isEmpty())
*result = generateFallbackData(topCmakeFile,
sourceDirectory,
buildDirectory,
result->errorMessage);
} else {
*result = extractData(data, sourceDirectory, buildDirectory); *result = extractData(data, sourceDirectory, buildDirectory);
} else
if (!result->errorMessage.isEmpty()) {
qWarning() << result->errorMessage; qWarning() << result->errorMessage;
}
fi.reportResult(result); fi.reportResult(result);
}); });
onResultReady(m_future.value(), onResultReady(m_future.value(),
this, this,
[this, topCmakeFile, sourceDirectory, buildDirectory, restoredFromBackup]( [this, sourceDirectory, buildDirectory, restoredFromBackup](
const std::shared_ptr<FileApiQtcData> &value) { const std::shared_ptr<FileApiQtcData> &value) {
m_isParsing = false; m_isParsing = false;
m_cache = std::move(value->cache); m_cache = std::move(value->cache);
@@ -348,6 +330,16 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf
QTC_CHECK(settingsFile.writeFileContents(contents)); QTC_CHECK(settingsFile.writeFileContents(contents));
} }
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{};
}
int FileApiReader::lastCMakeExitCode() const int FileApiReader::lastCMakeExitCode() const
{ {
return m_lastCMakeExitCode; return m_lastCMakeExitCode;

View File

@@ -71,8 +71,6 @@ public:
QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage); QList<CMakeBuildTarget> takeBuildTargets(QString &errorMessage);
CMakeConfig takeParsedConfiguration(QString &errorMessage); CMakeConfig takeParsedConfiguration(QString &errorMessage);
QString ctestPath() const; QString ctestPath() const;
std::unique_ptr<CMakeProjectNode> generateProjectTree(
const ProjectExplorer::TreeScanner::Result &allFiles, bool failedToParse);
ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage); ProjectExplorer::RawProjectParts createRawProjectParts(QString &errorMessage);
bool isMultiConfig() const; bool isMultiConfig() const;
@@ -80,6 +78,10 @@ public:
int lastCMakeExitCode() const; int lastCMakeExitCode() const;
std::unique_ptr<CMakeProjectNode> rootProjectNode();
Utils::FilePath topCmakeFile() const;
signals: signals:
void configurationStarted() const; void configurationStarted() const;
void dataAvailable(bool restoredFromBackup) const; void dataAvailable(bool restoredFromBackup) const;