CMakePM: Add CMake Profiler action

Change-Id: I17f258834724c37f0933d18b6214851be1965913
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
Cristian Adam
2023-09-21 19:11:01 +02:00
parent 1d5ecdb5c7
commit ed1568309b
9 changed files with 88 additions and 12 deletions

View File

@@ -201,7 +201,8 @@ void CMakeBuildSystem::triggerParsing()
m_reader.parse(reparseParameters & REPARSE_FORCE_CMAKE_RUN,
reparseParameters & REPARSE_FORCE_INITIAL_CONFIGURATION,
reparseParameters & REPARSE_FORCE_EXTRA_CONFIGURATION,
(reparseParameters & REPARSE_DEBUG) && isDebuggable);
(reparseParameters & REPARSE_DEBUG) && isDebuggable,
reparseParameters & REPARSE_PROFILING);
}
void CMakeBuildSystem::requestDebugging()
@@ -806,6 +807,13 @@ void CMakeBuildSystem::runCMakeWithExtraArguments()
reparse(REPARSE_FORCE_CMAKE_RUN | REPARSE_FORCE_EXTRA_CONFIGURATION | REPARSE_URGENT);
}
void CMakeBuildSystem::runCMakeWithProfiling()
{
qCDebug(cmakeBuildSystemLog) << "Requesting parse due \"CMake Profiler\" command";
reparse(REPARSE_FORCE_CMAKE_RUN | REPARSE_URGENT | REPARSE_FORCE_EXTRA_CONFIGURATION
| REPARSE_PROFILING);
}
void CMakeBuildSystem::stopCMakeRun()
{
qCDebug(cmakeBuildSystemLog) << buildConfiguration()->displayName()

View File

@@ -71,6 +71,7 @@ public:
void runCMake();
void runCMakeAndScanProjectTree();
void runCMakeWithExtraArguments();
void runCMakeWithProfiling();
void stopCMakeRun();
bool persistCMakeState();
@@ -151,6 +152,7 @@ private:
REPARSE_FORCE_EXTRA_CONFIGURATION = (1 << 2), // Force extra configuration arguments to cmake
REPARSE_URGENT = (1 << 3), // Do not delay the parser run by 1s
REPARSE_DEBUG = (1 << 4), // Start with debugging
REPARSE_PROFILING = (1 << 5), // Start profiling
};
void reparse(int reparseParameters);
QString reparseParametersString(int reparseFlags);

View File

@@ -10,6 +10,7 @@ const char CMAKE_MIMETYPE[] = "text/x-cmake";
const char CMAKE_PROJECT_MIMETYPE[] = "text/x-cmake-project";
const char CMAKE_EDITOR_ID[] = "CMakeProject.CMakeEditor";
const char RUN_CMAKE[] = "CMakeProject.RunCMake";
const char RUN_CMAKE_PROFILER[] = "CMakeProject.RunCMakeProfiler";
const char CLEAR_CMAKE_CACHE[] = "CMakeProject.ClearCache";
const char RESCAN_PROJECT[] = "CMakeProject.RescanProject";
const char RUN_CMAKE_CONTEXT_MENU[] = "CMakeProject.RunCMakeContextMenu";

View File

@@ -21,11 +21,15 @@
#include <cppeditor/cpptoolsreuse.h>
#include <debugger/analyzer/analyzerconstants.h>
#include <debugger/analyzer/analyzermanager.h>
#include <projectexplorer/buildmanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <projectexplorer/projecttree.h>
#include <projectexplorer/runcontrol.h>
#include <projectexplorer/target.h>
#include <utils/checkablemessagebox.h>
@@ -48,6 +52,7 @@ CMakeManager::CMakeManager()
, m_rescanProjectAction(new QAction(QIcon(), Tr::tr("Rescan Project"), this))
, m_reloadCMakePresetsAction(
new QAction(Utils::Icons::RELOAD.icon(), Tr::tr("Reload CMake Presets"), this))
, m_cmakeProfilerAction(new QAction(QIcon(), Tr::tr("CMake Profiler"), this))
{
Core::ActionContainer *mbuild =
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_BUILDPROJECT);
@@ -57,6 +62,8 @@ CMakeManager::CMakeManager()
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_SUBPROJECTCONTEXT);
Core::ActionContainer *mfile =
Core::ActionManager::actionContainer(ProjectExplorer::Constants::M_FILECONTEXT);
Core::ActionContainer *manalyzer =
Core::ActionManager::actionContainer(Debugger::Constants::M_DEBUG_ANALYZER);
const Core::Context projectContext(CMakeProjectManager::Constants::CMAKE_PROJECT_ID);
const Core::Context globalContext(Core::Constants::C_GLOBAL);
@@ -128,6 +135,16 @@ CMakeManager::CMakeManager()
mbuild->addAction(command, ProjectExplorer::Constants::G_BUILD_BUILD);
connect(m_buildFileAction, &QAction::triggered, this, [this] { buildFile(); });
// CMake Profiler
command = Core::ActionManager::registerAction(m_cmakeProfilerAction,
Constants::RUN_CMAKE_PROFILER,
globalContext);
command->setDescription(m_cmakeProfilerAction->text());
manalyzer->addAction(command, Debugger::Constants::G_ANALYZER_TOOLS);
connect(m_cmakeProfilerAction, &QAction::triggered, this, [this] {
runCMakeWithProfiling(ProjectManager::startupBuildSystem());
});
connect(ProjectManager::instance(), &ProjectManager::startupProjectChanged, this, [this] {
updateCmakeActions(ProjectTree::currentNode());
});
@@ -150,6 +167,7 @@ void CMakeManager::updateCmakeActions(Node *node)
m_runCMakeActionContextMenu->setEnabled(visible);
m_clearCMakeCacheAction->setVisible(visible);
m_rescanProjectAction->setVisible(visible);
m_cmakeProfilerAction->setEnabled(visible);
const bool reloadPresetsVisible = [project] {
if (!project)
@@ -180,6 +198,38 @@ void CMakeManager::runCMake(BuildSystem *buildSystem)
cmakeBuildSystem->runCMake();
}
void CMakeManager::runCMakeWithProfiling(BuildSystem *buildSystem)
{
auto cmakeBuildSystem = dynamic_cast<CMakeBuildSystem *>(buildSystem);
QTC_ASSERT(cmakeBuildSystem, return );
if (ProjectExplorerPlugin::saveModifiedFiles()) {
// cmakeBuildSystem->runCMakeWithProfiling() below will trigger Target::buildSystemUpdated
// which will ensure that the "cmake-profile.json" has been created and we can load the viewer
std::unique_ptr<QObject> context{new QObject};
QObject *pcontext = context.get();
QObject::connect(cmakeBuildSystem->target(),
&Target::buildSystemUpdated,
pcontext,
[context = std::move(context)]() mutable {
context.reset();
Core::Command *ctfVisualiserLoadTrace = Core::ActionManager::command(
"Analyzer.Menu.StartAnalyzer.CtfVisualizer.LoadTrace");
if (ctfVisualiserLoadTrace) {
auto *action = ctfVisualiserLoadTrace->actionForContext(
Core::Constants::C_GLOBAL);
const FilePath file = TemporaryDirectory::masterDirectoryFilePath()
/ "cmake-profile.json";
action->setData(file.nativePath());
emit ctfVisualiserLoadTrace->action()->triggered();
}
});
cmakeBuildSystem->runCMakeWithProfiling();
}
}
void CMakeManager::rescanProject(BuildSystem *buildSystem)
{
auto cmakeBuildSystem = dynamic_cast<CMakeBuildSystem *>(buildSystem);

View File

@@ -25,6 +25,7 @@ private:
void updateCmakeActions(ProjectExplorer::Node *node);
void clearCMakeCache(ProjectExplorer::BuildSystem *buildSystem);
void runCMake(ProjectExplorer::BuildSystem *buildSystem);
void runCMakeWithProfiling(ProjectExplorer::BuildSystem *buildSystem);
void rescanProject(ProjectExplorer::BuildSystem *buildSystem);
void buildFileContextMenu();
void buildFile(ProjectExplorer::Node *node = nullptr);
@@ -39,6 +40,7 @@ private:
QAction *m_buildFileContextMenu;
QAction *m_reloadCMakePresetsAction;
Utils::ParameterAction *m_buildFileAction;
QAction *m_cmakeProfilerAction;
};
} // namespace Internal

View File

@@ -84,7 +84,8 @@ void FileApiReader::resetData()
void FileApiReader::parse(bool forceCMakeRun,
bool forceInitialConfiguration,
bool forceExtraConfiguration,
bool debugging)
bool debugging,
bool profiling)
{
qCDebug(cmakeFileApiMode) << "Parse called with arguments: ForceCMakeRun:" << forceCMakeRun
<< " - forceConfiguration:" << forceInitialConfiguration
@@ -109,6 +110,12 @@ void FileApiReader::parse(bool forceCMakeRun,
}
}
if (profiling) {
const FilePath file = TemporaryDirectory::masterDirectoryFilePath() / "cmake-profile.json";
args << "--profiling-format=google-trace"
<< "--profiling-output=" + file.path();
}
qCDebug(cmakeFileApiMode) << "Parameters request these CMake arguments:" << args;
const FilePath replyFile = FileApiParser::scanForCMakeReplyFile(m_parameters.buildDirectory);

View File

@@ -41,7 +41,8 @@ public:
void parse(bool forceCMakeRun,
bool forceInitialConfiguration,
bool forceExtraConfiguration,
bool debugging);
bool debugging,
bool profiling);
void stop();
void stopCMakeRun();

View File

@@ -58,7 +58,15 @@ CtfVisualizerTool::CtfVisualizerTool()
m_loadJson.reset(new QAction(Tr::tr("Load JSON File"), options));
Core::Command *command = Core::ActionManager::registerAction(m_loadJson.get(), Constants::CtfVisualizerTaskLoadJson,
globalContext);
connect(m_loadJson.get(), &QAction::triggered, this, &CtfVisualizerTool::loadJson);
connect(m_loadJson.get(), &QAction::triggered, this, [this] {
QString filename = m_loadJson->data().toString();
if (filename.isEmpty())
filename = QFileDialog::getOpenFileName(ICore::dialogParent(),
Tr::tr("Load Chrome Trace Format File"),
"",
Tr::tr("JSON File (*.json)"));
loadJson(filename);
});
options->addAction(command);
m_perspective.setAboutToActivateCallback([this]() { createViews(); });
@@ -142,21 +150,18 @@ Timeline::TimelineZoomControl *CtfVisualizerTool::zoomControl() const
return m_zoomControl.get();
}
void CtfVisualizerTool::loadJson()
void CtfVisualizerTool::loadJson(const QString &filename)
{
if (m_isLoading)
return;
m_isLoading = true;
QString filename = QFileDialog::getOpenFileName(
ICore::dialogParent(), Tr::tr("Load Chrome Trace Format File"),
"", Tr::tr("JSON File (*.json)"));
if (filename.isEmpty()) {
m_isLoading = false;
return;
}
m_isLoading = true;
auto *futureInterface = new QFutureInterface<void>();
auto *task = new QFuture<void>(futureInterface);

View File

@@ -34,7 +34,7 @@ public:
CtfTraceManager *traceManager() const;
Timeline::TimelineZoomControl *zoomControl() const;
void loadJson();
void loadJson(const QString &filename);
private:
void createViews();