forked from qt-creator/qt-creator
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 <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -1663,6 +1663,36 @@ void CMakeBuildConfiguration::buildTarget(const QString &buildTarget)
|
|||||||
cmBs->setBuildTargets(originalBuildTargets);
|
cmBs->setBuildTargets(originalBuildTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMakeBuildConfiguration::reBuildTarget(const QString &cleanTarget, const QString &buildTarget)
|
||||||
|
{
|
||||||
|
auto cmBs = qobject_cast<CMakeBuildStep *>(
|
||||||
|
findOrDefault(buildSteps()->steps(), [](const BuildStep *bs) {
|
||||||
|
return bs->id() == Constants::CMAKE_BUILD_STEP_ID;
|
||||||
|
}));
|
||||||
|
auto cmCs = qobject_cast<CMakeBuildStep *>(
|
||||||
|
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
|
CMakeConfig CMakeBuildSystem::configurationFromCMake() const
|
||||||
{
|
{
|
||||||
return m_configurationFromCMake;
|
return m_configurationFromCMake;
|
||||||
|
@@ -66,6 +66,7 @@ public:
|
|||||||
|
|
||||||
// Context menu action:
|
// Context menu action:
|
||||||
void buildTarget(const QString &buildTarget);
|
void buildTarget(const QString &buildTarget);
|
||||||
|
void reBuildTarget(const QString &cleanTarget, const QString &buildTarget);
|
||||||
ProjectExplorer::BuildSystem *buildSystem() const final;
|
ProjectExplorer::BuildSystem *buildSystem() const final;
|
||||||
|
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
|
@@ -443,9 +443,37 @@ CommandLine CMakeBuildStep::cmakeCommand() const
|
|||||||
project = buildConfiguration()->project();
|
project = buildConfiguration()->project();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
||||||
|
const bool hasSubprojectBuild = bs && bs->hasSubprojectBuildSupport();
|
||||||
|
bool ninjaSubprojectClean = false;
|
||||||
|
|
||||||
|
// Subprojects have subdir/<command> 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(
|
cmd.addArgs(
|
||||||
{"--build",
|
{"--build",
|
||||||
CMakeToolManager::mappedFilePath(project, buildDirectory).path()});
|
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);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd.addArgs({"--build", CMakeToolManager::mappedFilePath(project, buildDirectory).path()});
|
||||||
|
|
||||||
cmd.addArg("--target");
|
cmd.addArg("--target");
|
||||||
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
|
cmd.addArgs(Utils::transform(m_buildTargets, [this](const QString &s) {
|
||||||
@@ -455,10 +483,10 @@ CommandLine CMakeBuildStep::cmakeCommand() const
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}));
|
}));
|
||||||
|
}
|
||||||
if (useStaging())
|
if (useStaging())
|
||||||
cmd.addArg("install");
|
cmd.addArg("install");
|
||||||
|
|
||||||
auto bs = qobject_cast<CMakeBuildSystem *>(buildSystem());
|
|
||||||
if (bs && bs->isMultiConfigReader()) {
|
if (bs && bs->isMultiConfigReader()) {
|
||||||
cmd.addArg("--config");
|
cmd.addArg("--config");
|
||||||
if (m_configuration)
|
if (m_configuration)
|
||||||
@@ -483,6 +511,12 @@ CommandLine CMakeBuildStep::cmakeCommand() const
|
|||||||
cmd.addArgs("-allowProvisioningUpdates", CommandLine::Raw);
|
cmd.addArgs("-allowProvisioningUpdates", CommandLine::Raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ninjaSubprojectClean) {
|
||||||
|
if (!toolArgumentsSpecified)
|
||||||
|
cmd.addArg("--");
|
||||||
|
cmd.addArgs({"-t", "clean"});
|
||||||
|
}
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -839,6 +839,16 @@ CMakeBuildSystem::projectFileArgumentPosition(const QString &targetName, const Q
|
|||||||
return std::nullopt;
|
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,
|
RemovedFilesFromProject CMakeBuildSystem::removeFiles(Node *context,
|
||||||
const FilePaths &filePaths,
|
const FilePaths &filePaths,
|
||||||
FilePaths *notRemoved)
|
FilePaths *notRemoved)
|
||||||
@@ -1193,6 +1203,13 @@ void CMakeBuildSystem::buildCMakeTarget(const QString &buildTarget)
|
|||||||
cmakeBuildConfiguration()->buildTarget(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()
|
bool CMakeBuildSystem::persistCMakeState()
|
||||||
{
|
{
|
||||||
BuildDirParameters parameters(this);
|
BuildDirParameters parameters(this);
|
||||||
|
@@ -81,6 +81,7 @@ public:
|
|||||||
|
|
||||||
// Context menu actions:
|
// Context menu actions:
|
||||||
void buildCMakeTarget(const QString &buildTarget);
|
void buildCMakeTarget(const QString &buildTarget);
|
||||||
|
void reBuildCMakeTarget(const QString &cleanTarget, const QString &buildTarget);
|
||||||
|
|
||||||
// Queries:
|
// Queries:
|
||||||
const QList<ProjectExplorer::BuildTargetInfo> appTargets() const;
|
const QList<ProjectExplorer::BuildTargetInfo> appTargets() const;
|
||||||
@@ -128,6 +129,9 @@ public:
|
|||||||
const QHash<QString, Utils::Link> &dotCMakeFilesHash() const { return m_dotCMakeFilesHash; }
|
const QHash<QString, Utils::Link> &dotCMakeFilesHash() const { return m_dotCMakeFilesHash; }
|
||||||
const QHash<QString, Utils::Link> &findPackagesFilesHash() const { return m_findPackagesFilesHash; }
|
const QHash<QString, Utils::Link> &findPackagesFilesHash() const { return m_findPackagesFilesHash; }
|
||||||
|
|
||||||
|
QString cmakeGenerator() const;
|
||||||
|
bool hasSubprojectBuildSupport() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void configurationCleared();
|
void configurationCleared();
|
||||||
void configurationChanged(const CMakeConfig &config);
|
void configurationChanged(const CMakeConfig &config);
|
||||||
|
@@ -19,6 +19,12 @@ const char BUILD_FILE[] = "CMakeProject.BuildFile";
|
|||||||
const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory";
|
const char CMAKE_HOME_DIR[] = "CMakeProject.HomeDirectory";
|
||||||
const char QML_DEBUG_SETTING[] = "CMakeProject.EnableQmlDebugging";
|
const char QML_DEBUG_SETTING[] = "CMakeProject.EnableQmlDebugging";
|
||||||
const char RELOAD_CMAKE_PRESETS[] = "CMakeProject.ReloadCMakePresets";
|
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_SETTINGS_GROUP[] = "CMakeFormatter";
|
||||||
const char CMAKEFORMATTER_GENERAL_GROUP[] = "General";
|
const char CMAKEFORMATTER_GENERAL_GROUP[] = "General";
|
||||||
|
@@ -72,6 +72,10 @@ private:
|
|||||||
void updateBuildFileAction();
|
void updateBuildFileAction();
|
||||||
void enableBuildFileMenus(Node *node);
|
void enableBuildFileMenus(Node *node);
|
||||||
void reloadCMakePresets();
|
void reloadCMakePresets();
|
||||||
|
void enableBuildSubprojectContextMenu(Node *node);
|
||||||
|
void enableBuildSubprojectMenu();
|
||||||
|
void runSubprojectOperation(const QString &clean, const QString &build);
|
||||||
|
CMakeListsNode* currentListsNodeForEditor();
|
||||||
|
|
||||||
QAction *m_runCMakeAction;
|
QAction *m_runCMakeAction;
|
||||||
QAction *m_clearCMakeCacheAction;
|
QAction *m_clearCMakeCacheAction;
|
||||||
@@ -85,6 +89,12 @@ private:
|
|||||||
QAction *m_cmakeDebuggerAction;
|
QAction *m_cmakeDebuggerAction;
|
||||||
QAction *m_cmakeDebuggerSeparator;
|
QAction *m_cmakeDebuggerSeparator;
|
||||||
bool m_canDebugCMake = false;
|
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)
|
bool CMakeManager::isCMakeUrl(const QUrl &url)
|
||||||
@@ -182,6 +192,66 @@ CMakeManager::CMakeManager()
|
|||||||
.addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_BUILD)
|
.addToContainer(PEC::M_BUILDPROJECT, PEC::G_BUILD_BUILD)
|
||||||
.addOnTriggered(this, [this] { buildFile(); });
|
.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
|
// CMake Profiler
|
||||||
ActionBuilder(this, Constants::RUN_CMAKE_PROFILER)
|
ActionBuilder(this, Constants::RUN_CMAKE_PROFILER)
|
||||||
.setIcon(ProjectExplorer::Icons::CMAKE_LOGO.icon())
|
.setIcon(ProjectExplorer::Icons::CMAKE_LOGO.icon())
|
||||||
@@ -225,8 +295,10 @@ CMakeManager::CMakeManager()
|
|||||||
connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, [this] {
|
connect(BuildManager::instance(), &BuildManager::buildStateChanged, this, [this] {
|
||||||
updateCmakeActions(ProjectTree::currentNode());
|
updateCmakeActions(ProjectTree::currentNode());
|
||||||
});
|
});
|
||||||
connect(EditorManager::instance(), &EditorManager::currentEditorChanged,
|
connect(EditorManager::instance(), &EditorManager::currentEditorChanged, this, [this]() {
|
||||||
this, &CMakeManager::updateBuildFileAction);
|
updateBuildFileAction();
|
||||||
|
enableBuildSubprojectMenu();
|
||||||
|
});
|
||||||
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged,
|
connect(ProjectTree::instance(), &ProjectTree::currentNodeChanged,
|
||||||
this, &CMakeManager::updateCmakeActions);
|
this, &CMakeManager::updateCmakeActions);
|
||||||
|
|
||||||
@@ -257,6 +329,7 @@ void CMakeManager::updateCmakeActions(Node *node)
|
|||||||
m_reloadCMakePresetsAction->setVisible(reloadPresetsVisible);
|
m_reloadCMakePresetsAction->setVisible(reloadPresetsVisible);
|
||||||
|
|
||||||
enableBuildFileMenus(node);
|
enableBuildFileMenus(node);
|
||||||
|
enableBuildSubprojectContextMenu(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMakeManager::clearCMakeCache(BuildSystem *buildSystem)
|
void CMakeManager::clearCMakeCache(BuildSystem *buildSystem)
|
||||||
@@ -409,6 +482,93 @@ void CMakeManager::reloadCMakePresets()
|
|||||||
Core::ModeManager::setFocusToCurrentMode();
|
Core::ModeManager::setFocusToCurrentMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMakeManager::enableBuildSubprojectContextMenu(Node *node)
|
||||||
|
{
|
||||||
|
const Project *project = ProjectTree::projectForNode(node);
|
||||||
|
auto subProjectNode = dynamic_cast<const CMakeListsNode *>(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<CMakeBuildSystem *>(ProjectTree::currentBuildSystem())) {
|
||||||
|
auto subProject = dynamic_cast<const CMakeListsNode *>(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<const CMakeTargetNode *>(node->parentProjectNode());
|
||||||
|
if (!targetNode)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return dynamic_cast<CMakeListsNode*>(targetNode->parentProjectNode());
|
||||||
|
}
|
||||||
|
|
||||||
void CMakeManager::buildFile(Node *node)
|
void CMakeManager::buildFile(Node *node)
|
||||||
{
|
{
|
||||||
if (!node) {
|
if (!node) {
|
||||||
|
@@ -74,6 +74,16 @@ CMakePresetsNode::CMakePresetsNode(const FilePath &projectPath) :
|
|||||||
setListInProject(false);
|
setListInProject(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CMakeListsNode::hasSubprojectBuildSupport() const
|
||||||
|
{
|
||||||
|
return m_hasSubprojectBuildSupport;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMakeListsNode::setHasSubprojectBuildSupport(bool hasSubprojectBuildSupport)
|
||||||
|
{
|
||||||
|
m_hasSubprojectBuildSupport = hasSubprojectBuildSupport;
|
||||||
|
}
|
||||||
|
|
||||||
CMakeListsNode::CMakeListsNode(const FilePath &cmakeListPath) :
|
CMakeListsNode::CMakeListsNode(const FilePath &cmakeListPath) :
|
||||||
ProjectExplorer::ProjectNode(cmakeListPath)
|
ProjectExplorer::ProjectNode(cmakeListPath)
|
||||||
{
|
{
|
||||||
|
@@ -23,6 +23,8 @@ public:
|
|||||||
|
|
||||||
class CMakeListsNode : public ProjectExplorer::ProjectNode
|
class CMakeListsNode : public ProjectExplorer::ProjectNode
|
||||||
{
|
{
|
||||||
|
bool m_hasSubprojectBuildSupport{false};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMakeListsNode(const Utils::FilePath &cmakeListPath);
|
CMakeListsNode(const Utils::FilePath &cmakeListPath);
|
||||||
|
|
||||||
@@ -32,6 +34,9 @@ public:
|
|||||||
bool canAddSubProject(const Utils::FilePath &subProjectFilePath) const override;
|
bool canAddSubProject(const Utils::FilePath &subProjectFilePath) const override;
|
||||||
bool addSubProject(const Utils::FilePath &subProjectFilePath) override;
|
bool addSubProject(const Utils::FilePath &subProjectFilePath) override;
|
||||||
QStringList subProjectFileNamePatterns() const override;
|
QStringList subProjectFileNamePatterns() const override;
|
||||||
|
|
||||||
|
bool hasSubprojectBuildSupport() const;
|
||||||
|
void setHasSubprojectBuildSupport(bool hasSubprojectBuildSupport);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMakeProjectNode : public ProjectExplorer::ProjectNode
|
class CMakeProjectNode : public ProjectExplorer::ProjectNode
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <extensionsystem/iplugin.h>
|
#include <extensionsystem/iplugin.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildmanager.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
#include <projectexplorer/projecttree.h>
|
#include <projectexplorer/projecttree.h>
|
||||||
@@ -111,13 +112,16 @@ class CMakeProjectPlugin final : public ExtensionSystem::IPlugin
|
|||||||
|
|
||||||
void updateContextActions(ProjectExplorer::Node *node)
|
void updateContextActions(ProjectExplorer::Node *node)
|
||||||
{
|
{
|
||||||
|
const Project *project = ProjectTree::projectForNode(node);
|
||||||
|
|
||||||
auto targetNode = dynamic_cast<const CMakeTargetNode *>(node);
|
auto targetNode = dynamic_cast<const CMakeTargetNode *>(node);
|
||||||
const QString targetDisplayName = targetNode ? targetNode->displayName() : QString();
|
const QString targetDisplayName = targetNode ? targetNode->displayName() : QString();
|
||||||
|
const bool isVisible = targetNode && !BuildManager::isBuilding(project);
|
||||||
|
|
||||||
// Build Target:
|
// Build Target:
|
||||||
m_buildTargetContextAction->setParameter(targetDisplayName);
|
m_buildTargetContextAction->setParameter(targetDisplayName);
|
||||||
m_buildTargetContextAction->setEnabled(targetNode);
|
m_buildTargetContextAction->setEnabled(isVisible);
|
||||||
m_buildTargetContextAction->setVisible(targetNode);
|
m_buildTargetContextAction->setVisible(isVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action *m_buildTargetContextAction = nullptr;
|
Action *m_buildTargetContextAction = nullptr;
|
||||||
|
@@ -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<CMakeListsNode *>(node)) {
|
||||||
|
cmakeListsNode->setHasSubprojectBuildSupport(
|
||||||
|
result.cmakeGenerator.contains("Ninja")
|
||||||
|
|| result.cmakeGenerator.contains("Makefiles"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// extractData:
|
// extractData:
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -1018,11 +1032,13 @@ FileApiQtcData extractData(const QFuture<void> &cancelFuture, FileApiData &input
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
result.ctestPath = input.replyFile.ctestExecutable;
|
result.ctestPath = input.replyFile.ctestExecutable;
|
||||||
|
result.cmakeGenerator = input.replyFile.generator;
|
||||||
result.isMultiConfig = input.replyFile.isMultiConfig;
|
result.isMultiConfig = input.replyFile.isMultiConfig;
|
||||||
if (input.replyFile.isMultiConfig && input.replyFile.generator != "Ninja Multi-Config")
|
if (input.replyFile.isMultiConfig && input.replyFile.generator != "Ninja Multi-Config")
|
||||||
result.usesAllCapsTargets = true;
|
result.usesAllCapsTargets = true;
|
||||||
|
|
||||||
markCMakeModulesFromPrefixPathAsGenerated(result);
|
markCMakeModulesFromPrefixPathAsGenerated(result);
|
||||||
|
setSubprojectBuildSupport(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -48,6 +48,7 @@ public:
|
|||||||
ProjectExplorer::RawProjectParts projectParts;
|
ProjectExplorer::RawProjectParts projectParts;
|
||||||
std::unique_ptr<CMakeProjectNode> rootProjectNode;
|
std::unique_ptr<CMakeProjectNode> rootProjectNode;
|
||||||
QString ctestPath;
|
QString ctestPath;
|
||||||
|
QString cmakeGenerator;
|
||||||
bool isMultiConfig = false;
|
bool isMultiConfig = false;
|
||||||
bool usesAllCapsTargets = false;
|
bool usesAllCapsTargets = false;
|
||||||
};
|
};
|
||||||
|
@@ -290,6 +290,7 @@ void FileApiReader::endState(const FilePath &replyFilePath, bool restoredFromBac
|
|||||||
m_ctestPath = std::move(value->ctestPath);
|
m_ctestPath = std::move(value->ctestPath);
|
||||||
m_isMultiConfig = value->isMultiConfig;
|
m_isMultiConfig = value->isMultiConfig;
|
||||||
m_usesAllCapsTargets = value->usesAllCapsTargets;
|
m_usesAllCapsTargets = value->usesAllCapsTargets;
|
||||||
|
m_cmakeGenerator = value->cmakeGenerator;
|
||||||
|
|
||||||
if (value->errorMessage.isEmpty()) {
|
if (value->errorMessage.isEmpty()) {
|
||||||
emit this->dataAvailable(restoredFromBackup);
|
emit this->dataAvailable(restoredFromBackup);
|
||||||
@@ -347,6 +348,11 @@ void FileApiReader::writeConfigurationIntoBuildDirectory(const QStringList &conf
|
|||||||
QTC_ASSERT_EXPECTED(settingsFile.writeFileContents(contents), return);
|
QTC_ASSERT_EXPECTED(settingsFile.writeFileContents(contents), return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FileApiReader::cmakeGenerator() const
|
||||||
|
{
|
||||||
|
return m_cmakeGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CMakeProjectNode> FileApiReader::rootProjectNode()
|
std::unique_ptr<CMakeProjectNode> FileApiReader::rootProjectNode()
|
||||||
{
|
{
|
||||||
return std::exchange(m_rootProjectNode, {});
|
return std::exchange(m_rootProjectNode, {});
|
||||||
|
@@ -63,6 +63,8 @@ public:
|
|||||||
|
|
||||||
Utils::FilePath topCmakeFile() const;
|
Utils::FilePath topCmakeFile() const;
|
||||||
|
|
||||||
|
QString cmakeGenerator() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void configurationStarted() const;
|
void configurationStarted() const;
|
||||||
void dataAvailable(bool restoredFromBackup) const;
|
void dataAvailable(bool restoredFromBackup) const;
|
||||||
@@ -90,6 +92,7 @@ private:
|
|||||||
ProjectExplorer::RawProjectParts m_projectParts;
|
ProjectExplorer::RawProjectParts m_projectParts;
|
||||||
std::unique_ptr<CMakeProjectNode> m_rootProjectNode;
|
std::unique_ptr<CMakeProjectNode> m_rootProjectNode;
|
||||||
QString m_ctestPath;
|
QString m_ctestPath;
|
||||||
|
QString m_cmakeGenerator;
|
||||||
bool m_isMultiConfig = false;
|
bool m_isMultiConfig = false;
|
||||||
bool m_usesAllCapsTargets = false;
|
bool m_usesAllCapsTargets = false;
|
||||||
int m_lastCMakeExitCode = 0;
|
int m_lastCMakeExitCode = 0;
|
||||||
|
Reference in New Issue
Block a user