From 415391b2b8bb4521dcb788fdd9ca47caa39c7857 Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Thu, 29 Aug 2024 19:13:25 +0200 Subject: [PATCH] CMakePM: Add subdirectory build/clean/rebuild context menu support CMake has support for sub directory operations for the Ninja and Unix Makefiles generators. See the documentation at: * https://cmake.org/cmake/help/latest/generator/Ninja.html * https://cmake.org/cmake/help/latest/generator/Unix%20Makefiles.html Fixes: QTCREATORBUG-27588 Change-Id: If620902df1761cc39a7554d0a8c0291a19f49897 Reviewed-by: Marcus Tillmanns --- .../cmakebuildconfiguration.cpp | 30 ++++ .../cmakebuildconfiguration.h | 1 + .../cmakeprojectmanager/cmakebuildstep.cpp | 56 ++++-- .../cmakeprojectmanager/cmakebuildsystem.cpp | 17 ++ .../cmakeprojectmanager/cmakebuildsystem.h | 4 + .../cmakeprojectconstants.h | 6 + .../cmakeprojectmanager.cpp | 164 +++++++++++++++++- .../cmakeprojectmanager/cmakeprojectnodes.cpp | 10 ++ .../cmakeprojectmanager/cmakeprojectnodes.h | 5 + .../cmakeprojectplugin.cpp | 8 +- .../fileapidataextractor.cpp | 16 ++ .../fileapidataextractor.h | 1 + .../cmakeprojectmanager/fileapireader.cpp | 6 + .../cmakeprojectmanager/fileapireader.h | 3 + 14 files changed, 312 insertions(+), 15 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp index d397f0fd1cc..9e829f8ac44 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.cpp @@ -1663,6 +1663,36 @@ void CMakeBuildConfiguration::buildTarget(const QString &buildTarget) cmBs->setBuildTargets(originalBuildTargets); } +void CMakeBuildConfiguration::reBuildTarget(const QString &cleanTarget, const QString &buildTarget) +{ + auto cmBs = qobject_cast( + findOrDefault(buildSteps()->steps(), [](const BuildStep *bs) { + return bs->id() == Constants::CMAKE_BUILD_STEP_ID; + })); + auto cmCs = qobject_cast( + findOrDefault(cleanSteps()->steps(), [](const BuildStep *bs) { + return bs->id() == Constants::CMAKE_BUILD_STEP_ID; + })); + + QStringList originalBuildTargets; + if (cmBs) { + originalBuildTargets = cmBs->buildTargets(); + cmBs->setBuildTargets({buildTarget}); + } + QString originalCleanTarget; + if (cmCs) { + originalCleanTarget = cmCs->cleanTarget(); + cmCs->setBuildTargets({cleanTarget}); + } + + BuildManager::buildLists({cleanSteps(), buildSteps()}); + + if (cmBs) + cmBs->setBuildTargets(originalBuildTargets); + if (cmCs) + cmCs->setBuildTargets({originalCleanTarget}); +} + CMakeConfig CMakeBuildSystem::configurationFromCMake() const { return m_configurationFromCMake; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h index c2ac9dfd48f..77a84109035 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildconfiguration.h @@ -66,6 +66,7 @@ public: // Context menu action: void buildTarget(const QString &buildTarget); + void reBuildTarget(const QString &cleanTarget, const QString &buildTarget); ProjectExplorer::BuildSystem *buildSystem() const final; void addToEnvironment(Utils::Environment &env) const override; diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index 664315e8a91..8264860a098 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -443,22 +443,50 @@ CommandLine CMakeBuildStep::cmakeCommand() const project = buildConfiguration()->project(); } - cmd.addArgs( - {"--build", - CMakeToolManager::mappedFilePath(project, buildDirectory).path()}); + auto bs = qobject_cast(buildSystem()); + const bool hasSubprojectBuild = bs && bs->hasSubprojectBuildSupport(); + bool ninjaSubprojectClean = false; - cmd.addArg("--target"); - cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) { - if (s.isEmpty()) { - if (RunConfiguration *rc = target()->activeRunConfiguration()) - return rc->buildKey(); + // Subprojects have subdir/ structure + if (m_buildTargets.size() == 1 && m_buildTargets.front().contains("/") && hasSubprojectBuild) { + QString target = m_buildTargets.front(); + const auto separator = target.lastIndexOf("/"); + const QString path = target.left(separator); + const QString operation = target.mid(separator + 1); + + if (bs->cmakeGenerator().contains("Makefiles")) { + cmd.addArgs( + {"--build", + CMakeToolManager::mappedFilePath(project, buildDirectory.pathAppended(path)) + .path()}); + cmd.addArg("--target"); + cmd.addArg(operation); + } else { + cmd.addArgs( + {"--build", CMakeToolManager::mappedFilePath(project, buildDirectory).path()}); + + cmd.addArg("--target"); + if (operation == "clean") { + target = path + "/" + "all"; + ninjaSubprojectClean = true; + } + cmd.addArg(target); } - return s; - })); + } else { + cmd.addArgs({"--build", CMakeToolManager::mappedFilePath(project, buildDirectory).path()}); + + cmd.addArg("--target"); + cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) { + if (s.isEmpty()) { + if (RunConfiguration *rc = target()->activeRunConfiguration()) + return rc->buildKey(); + } + return s; + })); + } if (useStaging()) cmd.addArg("install"); - auto bs = qobject_cast(buildSystem()); if (bs && bs->isMultiConfigReader()) { cmd.addArg("--config"); if (m_configuration) @@ -483,6 +511,12 @@ CommandLine CMakeBuildStep::cmakeCommand() const cmd.addArgs("-allowProvisioningUpdates", CommandLine::Raw); } + if (ninjaSubprojectClean) { + if (!toolArgumentsSpecified) + cmd.addArg("--"); + cmd.addArgs({"-t", "clean"}); + } + return cmd; } diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp index 320f286036d..c06aaf83f1e 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.cpp @@ -839,6 +839,16 @@ CMakeBuildSystem::projectFileArgumentPosition(const QString &targetName, const Q return std::nullopt; } +QString CMakeBuildSystem::cmakeGenerator() const +{ + return m_reader.cmakeGenerator(); +} + +bool CMakeBuildSystem::hasSubprojectBuildSupport() const +{ + return cmakeGenerator().contains("Ninja") || cmakeGenerator().contains("Makefiles"); +} + RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context, const FilePaths &filePaths, FilePaths *notRemoved) @@ -1193,6 +1203,13 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget) cmakeBuildConfiguration()->buildTarget(buildTarget); } +void CMakeBuildSystem::reBuildCMakeTarget(const QString &cleanTarget, const QString &buildTarget) +{ + QTC_ASSERT(!cleanTarget.isEmpty() && !buildTarget.isEmpty(), return); + if (ProjectExplorerPlugin::saveModifiedFiles()) + cmakeBuildConfiguration()->reBuildTarget(cleanTarget, buildTarget); +} + bool CMakeBuildSystem::persistCMakeState() { BuildDirParameters parameters(this); diff --git a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h index b6827385908..c0f8c687d32 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildsystem.h +++ b/src/plugins/cmakeprojectmanager/cmakebuildsystem.h @@ -81,6 +81,7 @@ public: // Context menu actions: void buildCMakeTarget(const QString &buildTarget); + void reBuildCMakeTarget(const QString &cleanTarget, const QString &buildTarget); // Queries: const QList appTargets() const; @@ -128,6 +129,9 @@ public: const QHash &dotCMakeFilesHash() const { return m_dotCMakeFilesHash; } const QHash &findPackagesFilesHash() const { return m_findPackagesFilesHash; } + QString cmakeGenerator() const; + bool hasSubprojectBuildSupport() const; + signals: void configurationCleared(); void configurationChanged(const CMakeConfig &config); diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h index 04922b6e9db..ad903315604 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectconstants.h @@ -19,6 +19,12 @@ const char BUILD_FILE[] = "CMakeProject.BuildFile"; const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory"; const char QML_DEBUG_SETTING[] = "CMakeProject.EnableQmlDebugging"; const char RELOAD_CMAKE_PRESETS[] = "CMakeProject.ReloadCMakePresets"; +const char BUILD_SUBPROJECT[] = "CMakeProject.BuildSubProject"; +const char CLEAN_SUBPROJECT[] = "CMakeProject.CleanSubProject"; +const char REBUILD_SUBPROJECT[] = "CMakeProject.RebuildSubProject"; +const char BUILD_SUBPROJECT_CONTEXT_MENU[] = "CMakeProject.BuildSubProjectContextMenu"; +const char CLEAN_SUBPROJECT_CONTEXT_MENU[] = "CMakeProject.CleanSubProjectContextMenu"; +const char REBUILD_SUBPROJECT_CONTEXT_MENU[] = "CMakeProject.RebuildSubProjectContextMenu"; const char CMAKEFORMATTER_SETTINGS_GROUP[] = "CMakeFormatter"; const char CMAKEFORMATTER_GENERAL_GROUP[] = "General"; diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp index 1a8c818491a..5b70c994275 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.cpp @@ -72,6 +72,10 @@ private: void updateBuildFileAction(); void enableBuildFileMenus(Node *node); void reloadCMakePresets(); + void enableBuildSubprojectContextMenu(Node *node); + void enableBuildSubprojectMenu(); + void runSubprojectOperation(const QString &clean, const QString &build); + CMakeListsNode* currentListsNodeForEditor(); QAction *m_runCMakeAction; QAction *m_clearCMakeCacheAction; @@ -85,6 +89,12 @@ private: QAction *m_cmakeDebuggerAction; QAction *m_cmakeDebuggerSeparator; bool m_canDebugCMake = false; + Action *m_buildSubprojectContextAction = nullptr; + QAction *m_cleanSubprojectContextAction = nullptr; + QAction *m_rebuildSubprojectContextAction = nullptr; + Action *m_buildSubprojectAction = nullptr; + QAction *m_cleanSubprojectAction = nullptr; + QAction *m_rebuildSubprojectAction = nullptr; }; bool CMakeManager::isCMakeUrl(const QUrl &url) @@ -182,6 +192,66 @@ CMakeManager::CMakeManager() .addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_BUILD) .addOnTriggered(this, [this] { buildFile(); }); + // Subproject + ActionBuilder(this, Constants::BUILD_SUBPROJECT) + .setParameterText( + Tr::tr("Build &Subproject \"%1\""), + Tr::tr("Build &Subproject"), + ActionBuilder::AlwaysEnabled) + .setContext(projectContext) + .bindContextAction(&m_buildSubprojectAction) + .setCommandAttribute(Command::CA_Hide) + .setCommandAttribute(Command::CA_UpdateText) + .setCommandDescription(m_buildSubprojectAction->text()) + .addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_SUBPROJECT) + .addOnTriggered(this, [&] { runSubprojectOperation(QString(), "all"); }); + + ActionBuilder(this, Constants::REBUILD_SUBPROJECT) + .setText(Tr::tr("Rebuild")) + .setContext(projectContext) + .bindContextAction(&m_rebuildSubprojectAction) + .setCommandAttribute(Command::CA_Hide) + .addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_SUBPROJECT) + .addOnTriggered(this, [&] { runSubprojectOperation("clean", "all"); }); + + ActionBuilder(this, Constants::CLEAN_SUBPROJECT) + .setText(Tr::tr("Clean")) + .setContext(projectContext) + .bindContextAction(&m_cleanSubprojectAction) + .setCommandAttribute(Command::CA_Hide) + .addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_SUBPROJECT) + .addOnTriggered(this, [&] { runSubprojectOperation("clean", QString()); }); + + // Subproject context menus + ActionBuilder(this, Constants::BUILD_SUBPROJECT_CONTEXT_MENU) + .setParameterText( + Tr::tr("Build &Subproject \"%1\""), + Tr::tr("Build &Subproject"), + ActionBuilder::AlwaysEnabled) + .setContext(projectContext) + .bindContextAction(&m_buildSubprojectContextAction) + .setCommandAttribute(Command::CA_Hide) + .setCommandAttribute(Command::CA_UpdateText) + .setCommandDescription(m_buildSubprojectContextAction->text()) + .addToContainer(PEC::M_SUBPROJECTCONTEXT, PEC::G_PROJECT_BUILD) + .addOnTriggered(this, [&] { runSubprojectOperation(QString(), "all"); }); + + ActionBuilder(this, Constants::REBUILD_SUBPROJECT_CONTEXT_MENU) + .setText(Tr::tr("Rebuild")) + .setContext(projectContext) + .bindContextAction(&m_rebuildSubprojectContextAction) + .setCommandAttribute(Command::CA_Hide) + .addToContainer(PEC::M_SUBPROJECTCONTEXT, PEC::G_PROJECT_BUILD) + .addOnTriggered(this, [&] { runSubprojectOperation("clean", "all"); }); + + ActionBuilder(this, Constants::CLEAN_SUBPROJECT_CONTEXT_MENU) + .setText(Tr::tr("Clean")) + .setContext(projectContext) + .bindContextAction(&m_cleanSubprojectContextAction) + .setCommandAttribute(Command::CA_Hide) + .addToContainer(PEC::M_SUBPROJECTCONTEXT, PEC::G_PROJECT_BUILD) + .addOnTriggered(this, [&] { runSubprojectOperation("clean", QString()); }); + // CMake Profiler ActionBuilder(this, Constants::RUN_CMAKE_PROFILER) .setIcon(ProjectExplorer::Icons::CMAKE_LOGO.icon()) @@ -225,8 +295,10 @@ CMakeManager::CMakeManager() connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, [this] { updateCmakeActions(ProjectTree::currentNode()); }); - connect(EditorManager::instance(), &EditorManager::currentEditorChanged, - this, &CMakeManager::updateBuildFileAction); + connect(EditorManager::instance(), &EditorManager::currentEditorChanged, this, [this]() { + updateBuildFileAction(); + enableBuildSubprojectMenu(); + }); connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged, this, &CMakeManager::updateCmakeActions); @@ -257,6 +329,7 @@ void CMakeManager::updateCmakeActions(Node *node) m_reloadCMakePresetsAction->setVisible(reloadPresetsVisible); enableBuildFileMenus(node); + enableBuildSubprojectContextMenu(node); } void CMakeManager::clearCMakeCache(BuildSystem *buildSystem) @@ -409,6 +482,93 @@ void CMakeManager::reloadCMakePresets() Core::ModeManager::setFocusToCurrentMode(); } +void CMakeManager::enableBuildSubprojectContextMenu(Node *node) +{ + const Project *project = ProjectTree::projectForNode(node); + auto subProjectNode = dynamic_cast(node); + + const QString subProjectDisplayName = subProjectNode ? subProjectNode->displayName() + : QString(); + const bool subProjectVisible = subProjectNode && subProjectNode->hasSubprojectBuildSupport() + && !BuildManager::isBuilding(project); + + m_buildSubprojectContextAction->setParameter(subProjectDisplayName); + m_buildSubprojectContextAction->setEnabled(subProjectVisible); + m_buildSubprojectContextAction->setVisible(subProjectVisible); + + m_cleanSubprojectContextAction->setEnabled(subProjectVisible); + m_cleanSubprojectContextAction->setVisible(subProjectVisible); + + m_rebuildSubprojectContextAction->setEnabled(subProjectVisible); + m_rebuildSubprojectContextAction->setVisible(subProjectVisible); +} + +void CMakeManager::enableBuildSubprojectMenu() +{ + auto subProjectNode = currentListsNodeForEditor(); + const Project *project = ProjectTree::projectForNode(subProjectNode); + + const QString subProjectDisplayName = subProjectNode ? subProjectNode->displayName() + : QString(); + const bool subProjectVisible = subProjectNode && subProjectNode->hasSubprojectBuildSupport() + && !BuildManager::isBuilding(project); + + m_buildSubprojectAction->setParameter(subProjectDisplayName); + m_buildSubprojectAction->setEnabled(subProjectVisible); + m_buildSubprojectAction->setVisible(subProjectVisible); + + m_cleanSubprojectAction->setEnabled(subProjectVisible); + m_cleanSubprojectAction->setVisible(subProjectVisible); + + m_rebuildSubprojectAction->setEnabled(subProjectVisible); + m_rebuildSubprojectAction->setVisible(subProjectVisible); +} + +void CMakeManager::runSubprojectOperation(const QString &clean, const QString &build) +{ + if (auto bs = qobject_cast(ProjectTree::currentBuildSystem())) { + auto subProject = dynamic_cast(ProjectTree::currentNode()); + + // We want to allow the build action from a source file when triggered from a keyboard seqnuence + if (!subProject) + subProject = currentListsNodeForEditor(); + + if (!subProject) + return; + + auto subProjectDir = subProject->filePath(); + auto projectFileDir = bs->project()->projectFilePath().parentDir(); + + auto relativePath = subProjectDir.relativeChildPath(projectFileDir); + if (clean.isEmpty()) { + bs->buildCMakeTarget(relativePath.path() + "/" + build); + } else if (build.isEmpty()) { + bs->buildCMakeTarget(relativePath.path() + "/" + clean); + } else { + bs->reBuildCMakeTarget( + relativePath.path() + "/" + clean, relativePath.path() + "/" + build); + } + } +} + +CMakeListsNode *CMakeManager::currentListsNodeForEditor() +{ + Core::IDocument *currentDocument = Core::EditorManager::currentDocument(); + if (!currentDocument) + return nullptr; + + const FilePath file = currentDocument->filePath(); + Node *n = ProjectTree::nodeForFile(file); + FileNode *node = n ? n->asFileNode() : nullptr; + if (!node) + return nullptr; + auto targetNode = dynamic_cast(node->parentProjectNode()); + if (!targetNode) + return nullptr; + + return dynamic_cast(targetNode->parentProjectNode()); +} + void CMakeManager::buildFile(Node *node) { if (!node) { diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp index 238d7862dd0..9f61b0de4d8 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.cpp @@ -74,6 +74,16 @@ CMakePresetsNode::CMakePresetsNode(const FilePath &projectPath) : setListInProject(false); } +bool CMakeListsNode::hasSubprojectBuildSupport() const +{ + return m_hasSubprojectBuildSupport; +} + +void CMakeListsNode::setHasSubprojectBuildSupport(bool hasSubprojectBuildSupport) +{ + m_hasSubprojectBuildSupport = hasSubprojectBuildSupport; +} + CMakeListsNode::CMakeListsNode(const FilePath &cmakeListPath) : ProjectExplorer::ProjectNode(cmakeListPath) { diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h index e9aa548e054..74718944017 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h +++ b/src/plugins/cmakeprojectmanager/cmakeprojectnodes.h @@ -23,6 +23,8 @@ public: class CMakeListsNode : public ProjectExplorer::ProjectNode { + bool m_hasSubprojectBuildSupport{false}; + public: CMakeListsNode(const Utils::FilePath &cmakeListPath); @@ -32,6 +34,9 @@ public: bool canAddSubProject(const Utils::FilePath &subProjectFilePath) const override; bool addSubProject(const Utils::FilePath &subProjectFilePath) override; QStringList subProjectFileNamePatterns() const override; + + bool hasSubprojectBuildSupport() const; + void setHasSubprojectBuildSupport(bool hasSubprojectBuildSupport); }; class CMakeProjectNode : public ProjectExplorer::ProjectNode diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp index f91c1438d24..22a2015b383 100644 --- a/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp +++ b/src/plugins/cmakeprojectmanager/cmakeprojectplugin.cpp @@ -24,6 +24,7 @@ #include +#include #include #include #include @@ -111,13 +112,16 @@ class CMakeProjectPlugin final : public ExtensionSystem::IPlugin void updateContextActions(ProjectExplorer::Node *node) { + const Project *project = ProjectTree::projectForNode(node); + auto targetNode = dynamic_cast(node); const QString targetDisplayName = targetNode ? targetNode->displayName() : QString(); + const bool isVisible = targetNode && !BuildManager::isBuilding(project); // Build Target: m_buildTargetContextAction->setParameter(targetDisplayName); - m_buildTargetContextAction->setEnabled(targetNode); - m_buildTargetContextAction->setVisible(targetNode); + m_buildTargetContextAction->setEnabled(isVisible); + m_buildTargetContextAction->setVisible(isVisible); } Action *m_buildTargetContextAction = nullptr; diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index 5f434472806..43af6c8a143 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -975,6 +975,20 @@ static void markCMakeModulesFromPrefixPathAsGenerated(FileApiQtcData &result) }); } +static void setSubprojectBuildSupport(FileApiQtcData &result) +{ + if (!result.rootProjectNode) + return; + + result.rootProjectNode->forEachGenericNode([&](Node *node) { + if (auto cmakeListsNode = dynamic_cast(node)) { + cmakeListsNode->setHasSubprojectBuildSupport( + result.cmakeGenerator.contains("Ninja") + || result.cmakeGenerator.contains("Makefiles")); + } + }); +} + // -------------------------------------------------------------------- // extractData: // -------------------------------------------------------------------- @@ -1018,11 +1032,13 @@ FileApiQtcData extractData(const QFuture &cancelFuture, FileApiData &input return {}; result.ctestPath = input.replyFile.ctestExecutable; + result.cmakeGenerator = input.replyFile.generator; result.isMultiConfig = input.replyFile.isMultiConfig; if (input.replyFile.isMultiConfig && input.replyFile.generator != "Ninja Multi-Config") result.usesAllCapsTargets = true; markCMakeModulesFromPrefixPathAsGenerated(result); + setSubprojectBuildSupport(result); return result; } diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.h b/src/plugins/cmakeprojectmanager/fileapidataextractor.h index dbe562421e6..dfcb9993b77 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.h +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.h @@ -48,6 +48,7 @@ public: ProjectExplorer::RawProjectParts projectParts; std::unique_ptr rootProjectNode; QString ctestPath; + QString cmakeGenerator; bool isMultiConfig = false; bool usesAllCapsTargets = false; }; diff --git a/src/plugins/cmakeprojectmanager/fileapireader.cpp b/src/plugins/cmakeprojectmanager/fileapireader.cpp index ee943aa03ec..e4ee9e629e5 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.cpp +++ b/src/plugins/cmakeprojectmanager/fileapireader.cpp @@ -290,6 +290,7 @@ void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBac m_ctestPath = std::move(value->ctestPath); m_isMultiConfig = value->isMultiConfig; m_usesAllCapsTargets = value->usesAllCapsTargets; + m_cmakeGenerator = value->cmakeGenerator; if (value->errorMessage.isEmpty()) { emit this->dataAvailable(restoredFromBackup); @@ -347,6 +348,11 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf QTC_ASSERT_EXPECTED(settingsFile.writeFileContents(contents), return); } +QString FileApiReader::cmakeGenerator() const +{ + return m_cmakeGenerator; +} + std::unique_ptr FileApiReader::rootProjectNode() { return std::exchange(m_rootProjectNode, {}); diff --git a/src/plugins/cmakeprojectmanager/fileapireader.h b/src/plugins/cmakeprojectmanager/fileapireader.h index 1bf1e80332d..dca928cddc1 100644 --- a/src/plugins/cmakeprojectmanager/fileapireader.h +++ b/src/plugins/cmakeprojectmanager/fileapireader.h @@ -63,6 +63,8 @@ public: Utils::FilePath topCmakeFile() const; + QString cmakeGenerator() const; + signals: void configurationStarted() const; void dataAvailable(bool restoredFromBackup) const; @@ -90,6 +92,7 @@ private: ProjectExplorer::RawProjectParts m_projectParts; std::unique_ptr m_rootProjectNode; QString m_ctestPath; + QString m_cmakeGenerator; bool m_isMultiConfig = false; bool m_usesAllCapsTargets = false; int m_lastCMakeExitCode = 0;