From a8cbd17733c4c8613a926227c4a188d0a5e09f8e Mon Sep 17 00:00:00 2001 From: Cristian Adam Date: Wed, 17 Jul 2024 20:02:26 +0200 Subject: [PATCH] CMakePM: Implement "FOLDER" property for targets See the CMake documentation https://cmake.org/cmake/help/latest/ prop_tgt/FOLDER.html This allows placement of targets in the project view in specific folders like e.g. "tests" Qt Creator (ab)uses the FOLDER property for the "qtc_runnable" feature, see https://doc.qt.io/qtcreator/creator-run-settings.html which would not allow to have both. The "qtc_runnable" should be fixed by having a property "QTC_RUNNABLE" for a target and have Qt Creator parse the code. Fixes: QTCREATORBUG-28873 Change-Id: I73433de78b9a86f631ee9d7903db535b69b734f6 Reviewed-by: Alessandro Portale --- .../fileapidataextractor.cpp | 49 ++++++++++++++++--- .../cmakeprojectmanager/projecttreehelper.cpp | 20 -------- .../cmakeprojectmanager/projecttreehelper.h | 4 -- .../hello-widgets/CMakeLists.txt | 1 + 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp index c76af32e775..9bb7837dd9e 100644 --- a/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp +++ b/src/plugins/cmakeprojectmanager/fileapidataextractor.cpp @@ -33,6 +33,8 @@ namespace CMakeProjectManager::Internal { static Q_LOGGING_CATEGORY(cmakeLogger, "qtc.cmake.fileApiExtractor", QtWarningMsg); +static const char QTC_RUNNABLE[] = "qtc_runnable"; + // -------------------------------------------------------------------- // Helpers: // -------------------------------------------------------------------- @@ -275,7 +277,8 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t, || f.fragment.contains("Qt6Gui")); }); - ct.qtcRunnable = t.folderTargetProperty == "qtc_runnable"; + // FIXME: remove the usage of "qtc_runnable" by parsing the CMake code instead + ct.qtcRunnable = t.folderTargetProperty == QTC_RUNNABLE; // Extract library directories for executables: for (const FragmentInfo &f : t.link.value().fragments) { @@ -761,7 +764,8 @@ static void addGeneratedFilesNode(ProjectNode *targetRoot, const FilePath &topLe addCMakeVFolder(targetRoot, buildDir, 10, Tr::tr(""), std::move(nodes)); } -static void addTargets(const QFuture &cancelFuture, +static void addTargets(FolderNode *root, + const QFuture &cancelFuture, const QHash &cmakeListsNodes, const Configuration &config, const std::vector &targetDetails, @@ -772,23 +776,55 @@ static void addTargets(const QFuture &cancelFuture, for (const TargetDetails &t : targetDetails) targetDetailsHash.insert(t.id, &t); const TargetDetails defaultTargetDetails; - auto getTargetDetails = [&targetDetailsHash, &defaultTargetDetails](const QString &id) - -> const TargetDetails & { + auto getTargetDetails = [&targetDetailsHash, + &defaultTargetDetails](const QString &id) -> const TargetDetails & { auto it = targetDetailsHash.constFind(id); if (it != targetDetailsHash.constEnd()) return *it.value(); return defaultTargetDetails; }; + auto createTargetNode = [](auto &cmakeListsNodes, + const Utils::FilePath &dir, + const QString &displayName) -> CMakeTargetNode * { + auto *cmln = cmakeListsNodes.value(dir); + QTC_ASSERT(cmln, return nullptr); + + QString targetId = displayName; + + CMakeTargetNode *tn = static_cast( + cmln->findNode([&targetId](const Node *n) { return n->buildKey() == targetId; })); + if (!tn) { + auto newNode = std::make_unique(dir, displayName); + tn = newNode.get(); + cmln->addNode(std::move(newNode)); + } + tn->setDisplayName(displayName); + return tn; + }; + + QHash folderNodes; + for (const FileApiDetails::Target &t : config.targets) { if (cancelFuture.isCanceled()) return; const TargetDetails &td = getTargetDetails(t.id); + CMakeTargetNode *tNode{nullptr}; const FilePath dir = directorySourceDir(config, sourceDir, t.directory); - CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, dir, t.name); + // FIXME: remove the usage of "qtc_runnable" by parsing the CMake code instead + if (!td.folderTargetProperty.isEmpty() && td.folderTargetProperty != QTC_RUNNABLE) { + const FilePath folderDir = FilePath::fromString(td.folderTargetProperty); + if (!folderNodes.contains(folderDir)) + folderNodes.insert( + folderDir, createSourceGroupNode(td.folderTargetProperty, folderDir, root)); + + tNode = createTargetNode(folderNodes, folderDir, t.name); + } else { + tNode = createTargetNode(cmakeListsNodes, dir, t.name); + } QTC_ASSERT(tNode, continue); tNode->setTargetInformation(td.artifacts, td.type); @@ -821,7 +857,8 @@ static std::unique_ptr generateRootProjectNode(const QFuture &cmakeListsNo pn->setDisplayName(displayName); } -CMakeTargetNode *createTargetNode(const QHash &cmakeListsNodes, - const Utils::FilePath &dir, - const QString &displayName) -{ - ProjectNode *cmln = cmakeListsNodes.value(dir); - QTC_ASSERT(cmln, return nullptr); - - QString targetId = displayName; - - CMakeTargetNode *tn = static_cast( - cmln->findNode([&targetId](const Node *n) { return n->buildKey() == targetId; })); - if (!tn) { - auto newNode = std::make_unique(dir, displayName); - tn = newNode.get(); - cmln->addNode(std::move(newNode)); - } - tn->setDisplayName(displayName); - return tn; -} - template static std::unique_ptr cloneFolderNode(FolderNode *node) { diff --git a/src/plugins/cmakeprojectmanager/projecttreehelper.h b/src/plugins/cmakeprojectmanager/projecttreehelper.h index 35f7cf16a43..b3d1c2d58bd 100644 --- a/src/plugins/cmakeprojectmanager/projecttreehelper.h +++ b/src/plugins/cmakeprojectmanager/projecttreehelper.h @@ -43,10 +43,6 @@ QHash addCMakeLists( void createProjectNode(const QHash &cmakeListsNodes, const Utils::FilePath &dir, const QString &displayName); -CMakeTargetNode *createTargetNode( - const QHash &cmakeListsNodes, - const Utils::FilePath &dir, - const QString &displayName); void addFileSystemNodes(ProjectExplorer::ProjectNode *root, const std::shared_ptr &folderNode); diff --git a/tests/manual/cmakeprojectmanager/hello-widgets/CMakeLists.txt b/tests/manual/cmakeprojectmanager/hello-widgets/CMakeLists.txt index 8c0c413d663..77193e0be94 100644 --- a/tests/manual/cmakeprojectmanager/hello-widgets/CMakeLists.txt +++ b/tests/manual/cmakeprojectmanager/hello-widgets/CMakeLists.txt @@ -35,3 +35,4 @@ file(GLOB SOURCE_FILES CONFIGURE_DEPENDS *.cpp *.h *.ui) add_executable(hello-widgets-glob ${SOURCE_FILES}) target_link_libraries(hello-widgets-glob PRIVATE Qt6::Widgets) +set_target_properties(hello-widgets-glob PROPERTIES FOLDER "Glob")