diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index fac54a782e4..0d3dd00149e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -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() diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index d802797ebd6..cc27c599db5 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -71,6 +71,7 @@ public: void runCMake(); void runCMakeAndScanProjectTree(); void runCMakeWithExtraArguments(); + void runCMakeWithProfiling(); void stopCMakeRun(); bool persistCMakeState(); @@ -150,7 +151,8 @@ private: = (1 << 1), // Force initial configuration arguments to cmake 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_DEBUG = (1 << 4), // Start with debugging + REPARSE_PROFILING = (1 << 5), // Start profiling }; void reparse(int reparseParameters); QString reparseParametersString(int reparseFlags); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index 183e9501360..53180461f3e 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -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"; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index f90a3b71735..fc6be84a2b8 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -21,11 +21,15 @@ #include +#include +#include + #include #include #include #include #include +#include #include #include @@ -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(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 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(buildSystem); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h index c47d724c9b6..149fe65e1c4 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.h @@ -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 diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp index 080ba1bcf65..fed19ca3d2b 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.cpp +++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp @@ -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); diff --git a/src/plugins/cmakeprojectmanager/fileapireader.h b/src/plugins/cmakeprojectmanager/fileapireader.h index b013770982d..1bf1e80332d 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.h +++ b/src/plugins/cmakeprojectmanager/fileapireader.h @@ -41,7 +41,8 @@ public: void parse(bool forceCMakeRun, bool forceInitialConfiguration, bool forceExtraConfiguration, - bool debugging); + bool debugging, + bool profiling); void stop(); void stopCMakeRun(); diff --git a/src/plugins/ctfvisualizer/ctfvisualizertool.cpp b/src/plugins/ctfvisualizer/ctfvisualizertool.cpp index 5b13573bb3f..22b6bd50473 100644 --- a/src/plugins/ctfvisualizer/ctfvisualizertool.cpp +++ b/src/plugins/ctfvisualizer/ctfvisualizertool.cpp @@ -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(); auto *task = new QFuture(futureInterface); diff --git a/src/plugins/ctfvisualizer/ctfvisualizertool.h b/src/plugins/ctfvisualizer/ctfvisualizertool.h index 647ea3cb74c..baea670d5cf 100644 --- a/src/plugins/ctfvisualizer/ctfvisualizertool.h +++ b/src/plugins/ctfvisualizer/ctfvisualizertool.h @@ -34,7 +34,7 @@ public: CtfTraceManager *traceManager() const; Timeline::TimelineZoomControl *zoomControl() const; - void loadJson(); + void loadJson(const QString &filename); private: void createViews();