CMakePM: Add runers for custom targets marked as qtc_runnable

Sometimes we need to have the ability to run in Qt Creator a task that
is defined in CMake code.

For example you can have a Qt Creator plugin, which is a shared library,
and you want to start Qt Creator loading the plugin.

The following code will work now:

```
add_custom_target(run COMMAND ${CMAKE_COMMAND} -E echo "Hello World from
CMake")
set_target_properties(run PROPERTIES FOLDER "qtc_runnable")
```

Fixes: QTCREATORBUG-32324
Change-Id: Iba0169b6402a7974c011bd2c58e40b83dfb9857c
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
Cristian Adam
2025-01-16 20:51:41 +01:00
parent 8bf4c0b4a1
commit 5537a102e6
3 changed files with 39 additions and 4 deletions

View File

@@ -2109,6 +2109,35 @@ const QList<BuildTargetInfo> CMakeBuildSystem::appTargets() const
env.prependOrSetLibrarySearchPaths(librarySearchPaths(this, buildKey));
};
appTargetList.append(bti);
} else if (ct.targetType == UtilityType && ct.qtcRunnable) {
const QString buildKey = ct.title;
CMakeTool *cmakeTool = CMakeKitAspect::cmakeTool(target()->kit());
if (!cmakeTool)
continue;
// Skip the "all", "clean", "install" special targets.
if (CMakeBuildStep::specialTargets(m_reader.usesAllCapsTargets()).contains(buildKey))
continue;
BuildTargetInfo bti;
bti.displayName = ct.title;
// We need the build directory, which is proper set to the "clean" target
// and "clean" doesn't differ between single and multi-config generators
const FilePath workingDirectory
= Utils::findOrDefault(m_buildTargets, [](const CMakeBuildTarget &bt) {
return bt.title == "clean";
}).workingDirectory;
bti.targetFilePath = cmakeTool->cmakeExecutable();
bti.projectFilePath = ct.sourceDirectory.cleanPath();
bti.workingDirectory = workingDirectory;
bti.buildKey = buildKey;
bti.isQtcRunnable = ct.qtcRunnable;
bti.additionalData = QVariantMap{
{"arguments", QStringList{"--build", ".", "--target", buildKey}}};
appTargetList.append(bti);
}
}

View File

@@ -263,6 +263,9 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
ct.sourceFiles.append(sourceDirectory.resolvePath(si.path));
}
// FIXME: remove the usage of "qtc_runnable" by parsing the CMake code instead
ct.qtcRunnable = t.folderTargetProperty == QTC_RUNNABLE;
if (ct.targetType == ExecutableType) {
FilePaths librarySeachPaths;
// Is this a GUI application?
@@ -272,9 +275,6 @@ static CMakeBuildTarget toBuildTarget(const TargetDetails &t,
|| f.fragment.contains("Qt6Gui"));
});
// 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->fragments) {
if (f.role == "flags") // ignore all flags fragments

View File

@@ -143,8 +143,14 @@ void DesktopRunConfiguration::updateTargetInformation()
}
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
emit aspect<EnvironmentAspect>()->environmentChanged();
auto argumentsAsString = [bti]() {
return CommandLine{"", bti.additionalData.toMap()["arguments"].toStringList()}
.arguments();
};
aspect<ArgumentsAspect>()->setArguments(argumentsAsString());
emit aspect<EnvironmentAspect>()->environmentChanged();
}
}