4 KiB
CMake Package Detector
This proof-of-concept detects which packages are used in a CMake project without having to modify the project at all (in most cases.) This could be used to generate dependency data for KDE libraries and also 3rd party dependencies.
See my CMake Log Parser for another idea of how to parse dependency data from CMake. I think this is a better solution though.
How it works
As you may have seen before, lots of CMake projects (including KDE software) uses a module called FeatureSummary
. It prints out what packages are used in a project and also a whole host of other configurable information.
Here's the trimmed output from the feature summary in Tokodon:
-- The following REQUIRED packages have been found:
* ECM (required version >= 5.240.0)
* Gettext
* Qt6Keychain
Secure storage of account secrets
* KF6QQC2DesktopStyle
Preferred Qt Quick Controls style
* KF6KIO (required version >= 5.240.0)
Sharing content and downloading files
* KF6Purpose (required version >= 5.240.0)
Sharing content from other KDE applications
* KF6 (required version >= 5.240.0)
Required application components
* KF6DBusAddons (required version >= 5.240.0)
Single application support
* KF6WindowSystem (required version >= 5.240.0)
Misc windowing operations
* Qt6
Required application components
-- The following OPTIONAL packages have not been found:
* Qt6QmlCompilerPlusPrivate
* KUnifiedPush, <https://invent.kde.org/libraries/kunifiedpush>
Push notification support
-- The following REQUIRED packages have not been found:
* KF6KirigamiAddons (required version >= 0.11.40)
Required application components and runtime dependency
* MpvQt
CMake Package Detector overrides the default FeatureSummary
module with a custom version that includes a basic file output, which is then pre-processed a bit before outputting to stdout
.
The benefits of this over other solutions (some are described in this issue) is enormous:
Manual list keeping
CMake Package Detector can automatically update dependencies, as the CMakeLists for the project is now the single source of truth. It also handles if-else chains since it uses CMake under the hood, which eliminates classes of hand-written errors.
Using distribution packages (for build dependencies)
This encounters the same set of issues, whenever a new dependency is introduced then it will usually not be reflected in the distribution package for months at a time. Also, distributors tend to have to deal with dependency issues via trial and error, so the issue still exists but is handled by someone else and delayed.
(Also, not every module exists in a distribution.)
.kde-ci.yml
This file is still handwritten, and it usually concerns dependencies between KDE software and select 3rd party stuff.
Some kind of CMake log parser/manual generation
Since we use CMake itself to calculate dependency data, it's 1-to-1 as it is on developer machines which is big. And it happens on the configuration step, so it's extremely quick. Since it doesn't depend on errors (such as my log parser) then it's more pro-active than re-active.
Usage
Run main.py
and give it a project path, like so:
$ python main.py ~/kde/tokodon
And it should spit out a list of CMake packages needed, and this could be fed into something like dnf
with it's CMake()
query.
CMake Packages:
ECM
Qt6QmlIntegration
Qt6QmlModels
Qt6OpenGL
Qt6QuickTemplates2
Qt6QuickControls2
Qt6Svg
Qt6WebSockets
Qt6Test
...
Caveats
There is a few requirements for this to work correctly:
- The project must not use the
REQUIRED
argument onfind_package
. This stops the CMake configuration step and the package list will be incomplete. Instead, useset_package_properties
and setTYPE REQUIRED
there instead. - The project must use
FeatureSummary
(it should be doing this anyway, in my opinion.) It also must use thefeature_summary
function.