forked from qt-creator/qt-creator
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 <alessandro.portale@qt.io>
This commit is contained in:
@@ -33,6 +33,8 @@ namespace CMakeProjectManager::Internal {
|
|||||||
|
|
||||||
static Q_LOGGING_CATEGORY(cmakeLogger, "qtc.cmake.fileApiExtractor", QtWarningMsg);
|
static Q_LOGGING_CATEGORY(cmakeLogger, "qtc.cmake.fileApiExtractor", QtWarningMsg);
|
||||||
|
|
||||||
|
static const char QTC_RUNNABLE[] = "qtc_runnable";
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
// Helpers:
|
// Helpers:
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
@@ -275,7 +277,8 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|
|||||||
|| f.fragment.contains("Qt6Gui"));
|
|| 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:
|
// Extract library directories for executables:
|
||||||
for (const FragmentInfo &f : t.link.value().fragments) {
|
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("<Generated Files>"), std::move(nodes));
|
addCMakeVFolder(targetRoot, buildDir, 10, Tr::tr("<Generated Files>"), std::move(nodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addTargets(const QFuture<void> &cancelFuture,
|
static void addTargets(FolderNode *root,
|
||||||
|
const QFuture<void> &cancelFuture,
|
||||||
const QHash<FilePath, ProjectNode *> &cmakeListsNodes,
|
const QHash<FilePath, ProjectNode *> &cmakeListsNodes,
|
||||||
const Configuration &config,
|
const Configuration &config,
|
||||||
const std::vector<TargetDetails> &targetDetails,
|
const std::vector<TargetDetails> &targetDetails,
|
||||||
@@ -772,23 +776,55 @@ static void addTargets(const QFuture<void> &cancelFuture,
|
|||||||
for (const TargetDetails &t : targetDetails)
|
for (const TargetDetails &t : targetDetails)
|
||||||
targetDetailsHash.insert(t.id, &t);
|
targetDetailsHash.insert(t.id, &t);
|
||||||
const TargetDetails defaultTargetDetails;
|
const TargetDetails defaultTargetDetails;
|
||||||
auto getTargetDetails = [&targetDetailsHash, &defaultTargetDetails](const QString &id)
|
auto getTargetDetails = [&targetDetailsHash,
|
||||||
-> const TargetDetails & {
|
&defaultTargetDetails](const QString &id) -> const TargetDetails & {
|
||||||
auto it = targetDetailsHash.constFind(id);
|
auto it = targetDetailsHash.constFind(id);
|
||||||
if (it != targetDetailsHash.constEnd())
|
if (it != targetDetailsHash.constEnd())
|
||||||
return *it.value();
|
return *it.value();
|
||||||
return defaultTargetDetails;
|
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<CMakeTargetNode *>(
|
||||||
|
cmln->findNode([&targetId](const Node *n) { return n->buildKey() == targetId; }));
|
||||||
|
if (!tn) {
|
||||||
|
auto newNode = std::make_unique<CMakeTargetNode>(dir, displayName);
|
||||||
|
tn = newNode.get();
|
||||||
|
cmln->addNode(std::move(newNode));
|
||||||
|
}
|
||||||
|
tn->setDisplayName(displayName);
|
||||||
|
return tn;
|
||||||
|
};
|
||||||
|
|
||||||
|
QHash<FilePath, FolderNode *> folderNodes;
|
||||||
|
|
||||||
for (const FileApiDetails::Target &t : config.targets) {
|
for (const FileApiDetails::Target &t : config.targets) {
|
||||||
if (cancelFuture.isCanceled())
|
if (cancelFuture.isCanceled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const TargetDetails &td = getTargetDetails(t.id);
|
const TargetDetails &td = getTargetDetails(t.id);
|
||||||
|
|
||||||
|
CMakeTargetNode *tNode{nullptr};
|
||||||
const FilePath dir = directorySourceDir(config, sourceDir, t.directory);
|
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);
|
QTC_ASSERT(tNode, continue);
|
||||||
|
|
||||||
tNode->setTargetInformation(td.artifacts, td.type);
|
tNode->setTargetInformation(td.artifacts, td.type);
|
||||||
@@ -821,7 +857,8 @@ static std::unique_ptr<CMakeProjectNode> generateRootProjectNode(const QFuture<v
|
|||||||
if (cancelFuture.isCanceled())
|
if (cancelFuture.isCanceled())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
addTargets(cancelFuture,
|
addTargets(result.get(),
|
||||||
|
cancelFuture,
|
||||||
cmakeListsNodes,
|
cmakeListsNodes,
|
||||||
data.codemodel,
|
data.codemodel,
|
||||||
data.targetDetails,
|
data.targetDetails,
|
||||||
|
|||||||
@@ -173,26 +173,6 @@ void createProjectNode(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNo
|
|||||||
pn->setDisplayName(displayName);
|
pn->setDisplayName(displayName);
|
||||||
}
|
}
|
||||||
|
|
||||||
CMakeTargetNode *createTargetNode(const QHash<Utils::FilePath, ProjectNode *> &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<CMakeTargetNode *>(
|
|
||||||
cmln->findNode([&targetId](const Node *n) { return n->buildKey() == targetId; }));
|
|
||||||
if (!tn) {
|
|
||||||
auto newNode = std::make_unique<CMakeTargetNode>(dir, displayName);
|
|
||||||
tn = newNode.get();
|
|
||||||
cmln->addNode(std::move(newNode));
|
|
||||||
}
|
|
||||||
tn->setDisplayName(displayName);
|
|
||||||
return tn;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Result>
|
template<typename Result>
|
||||||
static std::unique_ptr<Result> cloneFolderNode(FolderNode *node)
|
static std::unique_ptr<Result> cloneFolderNode(FolderNode *node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,10 +43,6 @@ QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> addCMakeLists(
|
|||||||
void createProjectNode(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
|
void createProjectNode(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
|
||||||
const Utils::FilePath &dir,
|
const Utils::FilePath &dir,
|
||||||
const QString &displayName);
|
const QString &displayName);
|
||||||
CMakeTargetNode *createTargetNode(
|
|
||||||
const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cmakeListsNodes,
|
|
||||||
const Utils::FilePath &dir,
|
|
||||||
const QString &displayName);
|
|
||||||
|
|
||||||
void addFileSystemNodes(ProjectExplorer::ProjectNode *root,
|
void addFileSystemNodes(ProjectExplorer::ProjectNode *root,
|
||||||
const std::shared_ptr<ProjectExplorer::FolderNode> &folderNode);
|
const std::shared_ptr<ProjectExplorer::FolderNode> &folderNode);
|
||||||
|
|||||||
@@ -35,3 +35,4 @@ file(GLOB SOURCE_FILES CONFIGURE_DEPENDS *.cpp *.h *.ui)
|
|||||||
|
|
||||||
add_executable(hello-widgets-glob ${SOURCE_FILES})
|
add_executable(hello-widgets-glob ${SOURCE_FILES})
|
||||||
target_link_libraries(hello-widgets-glob PRIVATE Qt6::Widgets)
|
target_link_libraries(hello-widgets-glob PRIVATE Qt6::Widgets)
|
||||||
|
set_target_properties(hello-widgets-glob PROPERTIES FOLDER "Glob")
|
||||||
|
|||||||
Reference in New Issue
Block a user