CMake: Get some timings about the data update process

This should help to remove UI blocking by pointing to the costly
operations.

Change-Id: I8b3250e9ec5995c7b6a705337d60250554b77b53
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Tobias Hunger
2019-06-20 15:49:05 +02:00
parent a3d6839162
commit 129c0abb5a

View File

@@ -59,6 +59,7 @@
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <QDir> #include <QDir>
#include <QElapsedTimer>
#include <QSet> #include <QSet>
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -68,6 +69,25 @@ namespace CMakeProjectManager {
Q_LOGGING_CATEGORY(cmakeProjectLog, "qtc.cmake.project", QtWarningMsg); Q_LOGGING_CATEGORY(cmakeProjectLog, "qtc.cmake.project", QtWarningMsg);
class TraceTimer
{
public:
TraceTimer(const QString &msg)
: m_message(msg)
{
m_timer.start();
}
~TraceTimer()
{
qCInfo(cmakeProjectLog) << QString("%1 (%2ms)").arg(m_message).arg(m_timer.elapsed());
}
private:
QElapsedTimer m_timer;
QString m_message;
};
using namespace Internal; using namespace Internal;
static CMakeBuildConfiguration *activeBc(const CMakeProject *p) static CMakeBuildConfiguration *activeBc(const CMakeProject *p)
@@ -269,6 +289,7 @@ CMakeProject::~CMakeProject()
void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc) void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
{ {
TraceTimer updateProjectTotalTimer(__PRETTY_FUNCTION__);
qCDebug(cmakeProjectLog) << "Updating CMake project data"; qCDebug(cmakeProjectLog) << "Updating CMake project data";
const CMakeBuildConfiguration *aBc = activeBc(this); const CMakeBuildConfiguration *aBc = activeBc(this);
QString errorMessage; QString errorMessage;
@@ -277,103 +298,131 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
QTC_ASSERT(bc == aBc, return); QTC_ASSERT(bc == aBc, return);
QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return); QTC_ASSERT(m_treeScanner.isFinished() && !m_buildDirManager.isParsing(), return);
const QList<CMakeBuildTarget> buildTargets = m_buildDirManager.takeBuildTargets(errorMessage);
checkAndReportError(errorMessage);
bc->setBuildTargets(buildTargets);
qCDebug(cmakeProjectLog) << "Build target data set.";
const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration(errorMessage);
checkAndReportError(errorMessage);
bc->setConfigurationFromCMake(cmakeConfig);
qCDebug(cmakeProjectLog) << "CMake configuration data set.";
CMakeConfig patchedConfig = cmakeConfig;
{ {
CMakeConfigItem settingFileItem; TraceTimer buildTargetsTimer(" build targets");
settingFileItem.key = "ANDROID_DEPLOYMENT_SETTINGS_FILE"; const QList<CMakeBuildTarget> buildTargets = m_buildDirManager.takeBuildTargets(
settingFileItem.value = bc->buildDirectory() errorMessage);
.pathAppended("android_deployment_settings.json").toString().toUtf8(); checkAndReportError(errorMessage);
patchedConfig.append(settingFileItem); bc->setBuildTargets(buildTargets);
qCDebug(cmakeProjectLog) << "Build target data set.";
} }
CMakeConfig patchedConfig;
{
TraceTimer cacheTimer(" cache data (plus patching)");
const CMakeConfig cmakeConfig = m_buildDirManager.takeCMakeConfiguration(errorMessage);
checkAndReportError(errorMessage);
bc->setConfigurationFromCMake(cmakeConfig);
qCDebug(cmakeProjectLog) << "CMake configuration data set.";
QSet<QString> res; patchedConfig = cmakeConfig;
QStringList apps; {
for (const auto &target : bc->buildTargets()) { CMakeConfigItem settingFileItem;
if (target.targetType == CMakeProjectManager::DynamicLibraryType) { settingFileItem.key = "ANDROID_DEPLOYMENT_SETTINGS_FILE";
res.insert(target.executable.parentDir().toString()); settingFileItem.value = bc->buildDirectory()
apps.push_back(target.executable.toUserOutput()); .pathAppended("android_deployment_settings.json")
.toString()
.toUtf8();
patchedConfig.append(settingFileItem);
} }
// ### shall we add also the ExecutableType ?
} }
{ {
CMakeConfigItem paths; TraceTimer appsTimer(" application data");
paths.key = "ANDROID_SO_LIBS_PATHS"; QSet<QString> res;
paths.values = res.toList(); QStringList apps;
patchedConfig.append(paths); for (const auto &target : bc->buildTargets()) {
if (target.targetType == CMakeProjectManager::DynamicLibraryType) {
res.insert(target.executable.parentDir().toString());
apps.push_back(target.executable.toUserOutput());
}
// ### shall we add also the ExecutableType ?
}
{
CMakeConfigItem paths;
paths.key = "ANDROID_SO_LIBS_PATHS";
paths.values = res.toList();
patchedConfig.append(paths);
}
apps.sort();
{
CMakeConfigItem appsPaths;
appsPaths.key = "TARGETS_BUILD_PATH";
appsPaths.values = apps;
patchedConfig.append(appsPaths);
}
} }
apps.sort();
{ {
CMakeConfigItem appsPaths; TraceTimer projectTreeTimer(" project tree");
appsPaths.key = "TARGETS_BUILD_PATH"; auto newRoot = generateProjectTree(m_allFiles);
appsPaths.values = apps; if (newRoot) {
patchedConfig.append(appsPaths); setRootProjectNode(std::move(newRoot));
} if (rootProjectNode())
qCDebug(cmakeProjectLog) << "Application data regenerated."; setDisplayName(rootProjectNode()->displayName());
auto newRoot = generateProjectTree(m_allFiles); for (const CMakeBuildTarget &bt : bc->buildTargets()) {
if (newRoot) { const QString buildKey = CMakeTargetNode::generateId(bt.sourceDirectory, bt.title);
setRootProjectNode(std::move(newRoot)); if (ProjectNode *node = findNodeForBuildKey(buildKey)) {
if (rootProjectNode()) if (auto targetNode = dynamic_cast<CMakeTargetNode *>(node))
setDisplayName(rootProjectNode()->displayName()); targetNode->setConfig(patchedConfig);
}
for (const CMakeBuildTarget &bt : buildTargets) {
const QString buildKey = CMakeTargetNode::generateId(bt.sourceDirectory, bt.title);
if (ProjectNode *node = findNodeForBuildKey(buildKey)) {
if (auto targetNode = dynamic_cast<CMakeTargetNode *>(node))
targetNode->setConfig(patchedConfig);
} }
} }
} }
qCDebug(cmakeProjectLog) << "Project tree updated.";
Target *t = bc->target(); {
t->setApplicationTargets(bc->appTargets()); TraceTimer projectTreeTimer(" target updated");
t->setDeploymentData(bc->deploymentData()); Target *t = bc->target();
t->setApplicationTargets(bc->appTargets());
t->setDeploymentData(bc->deploymentData());
t->updateDefaultRunConfigurations(); t->updateDefaultRunConfigurations();
}
qDeleteAll(m_extraCompilers); {
m_extraCompilers = findExtraCompilers(); TraceTimer projectTreeTimer(" extra compilers");
CppTools::GeneratedCodeModelSupport::update(m_extraCompilers); qDeleteAll(m_extraCompilers);
qCDebug(cmakeProjectLog) << "Extra compilers updated."; m_extraCompilers = findExtraCompilers();
CppTools::GeneratedCodeModelSupport::update(m_extraCompilers);
qCDebug(cmakeProjectLog) << "Extra compilers updated.";
}
QtSupport::CppKitInfo kitInfo(this); QtSupport::CppKitInfo kitInfo(this);
QTC_ASSERT(kitInfo.isValid(), return); QTC_ASSERT(kitInfo.isValid(), return);
CppTools::RawProjectParts rpps = m_buildDirManager.createRawProjectParts(errorMessage); {
checkAndReportError(errorMessage); TraceTimer cxxCodemodelTimer(" cxx codemodel");
qCDebug(cmakeProjectLog) << "Raw project parts created."; CppTools::RawProjectParts rpps = m_buildDirManager.createRawProjectParts(errorMessage);
checkAndReportError(errorMessage);
qCDebug(cmakeProjectLog) << "Raw project parts created.";
for (CppTools::RawProjectPart &rpp : rpps) { for (CppTools::RawProjectPart &rpp : rpps) {
rpp.setQtVersion(kitInfo.projectPartQtVersion); // TODO: Check if project actually uses Qt. rpp.setQtVersion(
if (kitInfo.cxxToolChain) kitInfo.projectPartQtVersion); // TODO: Check if project actually uses Qt.
rpp.setFlagsForCxx({kitInfo.cxxToolChain, rpp.flagsForCxx.commandLineFlags}); if (kitInfo.cxxToolChain)
if (kitInfo.cToolChain) rpp.setFlagsForCxx({kitInfo.cxxToolChain, rpp.flagsForCxx.commandLineFlags});
rpp.setFlagsForC({kitInfo.cToolChain, rpp.flagsForC.commandLineFlags}); if (kitInfo.cToolChain)
rpp.setFlagsForC({kitInfo.cToolChain, rpp.flagsForC.commandLineFlags});
}
m_cppCodeModelUpdater->update({this, kitInfo, rpps});
}
{
TraceTimer qmlCodemodelTimer(" qml codemodel");
updateQmlJSCodeModel();
} }
m_cppCodeModelUpdater->update({this, kitInfo, rpps}); {
qCDebug(cmakeProjectLog) << "C++ codemodel updated."; TraceTimer resetTimer(" resetting builddirmanager");
m_buildDirManager.resetData();
}
updateQmlJSCodeModel(); {
qCDebug(cmakeProjectLog) << "QML codemodel updated."; TraceTimer emitTimer(" emitting signals");
emit fileListChanged();
m_buildDirManager.resetData(); bc->emitBuildTypeChanged();
qCDebug(cmakeProjectLog) << "CMake specific data was reset."; }
emit fileListChanged();
bc->emitBuildTypeChanged();
qCDebug(cmakeProjectLog) << "All CMake project data up to date."; qCDebug(cmakeProjectLog) << "All CMake project data up to date.";
} }
@@ -603,7 +652,10 @@ void CMakeProject::combineScanAndParse(CMakeBuildConfiguration *bc)
if (m_combinedScanAndParseResult) if (m_combinedScanAndParseResult)
updateProjectData(bc); updateProjectData(bc);
emitParsingFinished(m_combinedScanAndParseResult); {
TraceTimer parsingDoneTimer(" parsing finished signal");
emitParsingFinished(m_combinedScanAndParseResult);
}
} }
QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const