How to build KDE APP on Qt6
With the Qt6.4 release last month and the ongoing porting of most KDE Frameworks and Applications to Qt6, it’s time to write a post about how to build KDE applications on Qt6. This guide is intended for developers who want to port their own applications build on KDE frameworks.
I’ll use the porting of KWeather as an example. KWeather is a weather forecasting App build on top of Kirigami, it also relies heavily on KWeatherCore framework for its core functionality. So I’ll also cover the porting of KWeatherCore.
KDESRC-BUILD
KDESRC-BUILD is the tool that allows you to build any KDE software. If you don’t have KDESRC-BUILD installed yet, follow the link above and install it.
KDESRC-BUILD Configuration
After installing the KDESRC-BUILD and copying the sample configuration file to ~/.config/kdesrc-buildrc
,
we will edit some lines to make KDESRC-BUILD link Qt6 by default. First, we want create a separate folder to store the source files, build directories, and install root. We’ll choose ~/kde/qt6
as the root directory.
global
# Install directory for KDE software
kdedir ~/kde/qt6/usr
# Directory for downloaded source code
source-dir ~/kde/qt6/src
# Directory to build KDE into before installing
# relative to source-dir by default
build-dir ~/kde/qt6/build
...
end global
Then we need to change the include of the KDE Frameworks 5 and Qt5 configuration files to the corresponding KF6 and Qt6 ones.
...
end global
# Common options that should be set for some KDE modules no matter how
# kdesrc-build finds them. Do not comment these out unless you know
# what you are doing.
include /home/hany/kde/src/kdesrc-build/kf6-common-options-build-include
...
# KF5 and Plasma :)
include /home/hany/kde/src/kdesrc-build/kf6-qt6-build-include
# To change options for modules that have already been defined, use an
# 'options' block. See kf5-common-options-build-include for an example
That’s all for the KDESRC-BUILD configuration.
Try to build KWeather
Since we’re porting our app, it is very likely that the first build will fail, so it is advisable to pull all the source code first.
kdesrc-build --src-only kweather
will do just that.
Then we try to build by running kdesrc-build --refresh-build --no-src kweather
. And as we expected, the build failed. but don’t worry, let’s investigate the cause.
Building kweathercore from _cmdline (8/11)
Source update complete for kweathercore: Skipped
Preparing build system for kweathercore.
Removing files in build directory for kweathercore
Old build system cleaned, starting new build system.
Running cmake targeting Unix Makefiles...
Unable to configure kweathercore with KDE CMake
kweathercore didn't build, stopping here.
<<< PACKAGES FAILED TO BUILD >>>
kweathercore - file:///home/hany/kde/qt6/src/log/2022-10-05-01/kweathercore/cmake.log
* Installing "sample-kde-env-master.sh" would overwrite an existing file:
* /home/hany/.config/kde-env-master.sh
* If this is acceptable, please delete the existing file and re-run,
* or pass --delete-my-settings and re-run.
:-(
Your logs are saved in file:///home/hany/kde/qt6/src/log/2022-10-05-01
By examining the /home/hany/kde/qt6/src/log/2022-10-05-01/kweathercore/cmake.log
we found out the exact error is
-- Configuring done
CMake Error: The INTERFACE_QT_MAJOR_VERSION property of "Qt6::Core" does
not agree with the value of QT_MAJOR_VERSION already determined
for "KF5KWeatherCore".
At first glance, this error seems confusing. In reality, it says that the project (in this case KF5KWeatherCore) is still linked to Qt5, even though we have specified to link against Qt6. So we need to take a look at KWeatherCore. It turns out that KWeatherCore still hardcodes Qt5 in CMakeList, so a change needs to be made to make KWeatherCore Qt6 compatible.
Make CMakeList Qt6 compatible
Qt’s cmake-qt5-and-qt6-compatibility is a good place to start. In our case, we should first include Extra-CMake-Modules (which should already have been done for existing KDE software) and then replace any hardcoded reference to Qt5
with Qt${QT_VERSION_MAJOR}
. To see why, Volker Krause has an excellent post about it.
Edit KDESRC-BUILD configuration to specify Qt6
Now it is time to tell KDESRC-BUILD that KWeatherCore should be linked to Qt6. We simply set ${QT_VERSION_MAJOR}
cmake variable to 6
by adding a section to ~/.config/kdesrc-buildrc
options kweathercore
cmake-options DQT_MAJOR_VERSION=6
end options
Fix build issue for dependencies
Shortly after we had a build error with kemoticon
, we found out after looking at the source code that kemoticon
does not support Qt6. A search on KF6 workboard shows that kemoticon is deprecated in KDE Frameworks 6. Now it is time to determine exactly where kemoticon
is located in our dependency tree. kdesrc-build --dependency-tree kweather
shows that KWeatherCore
depends on kf5umbrella
, which in turn depends on kemoticon
.
KDE manages project dependency data (along with much other metadata) in (repo-metadata)[https://invent.kde.org/sysadmin/repo-metadata/-/tree/master/dependencies]. The files we are insterested in are dependency-data-stable-kf5-qt5
and dependency-data-kf5-qt5
, in particular dependency-data-kf5-qt5
since this is the file used to determine dependencies in KDESRC-BUILD. A quick search revealed that neither KWeather nor KWeatherCore depends on kf5umbrella
. Here’s the kicker: any project not included in frameworks
implicitly depends on kf5umbrella
unless explicitly stated otherwise. Since both KWeather and KWeatherCore are in extragear category, they implicitly depend on kf5umbrella
. The solution is simple: edit dependency-data-kf5-qt5
in our local repository (the repo is located in ~/kde/qt6/src/sysadmin-repo-metadata
) to remove the dependency.
extragear/libs/kweathercore: -frameworks/kf5umbrella
extragear/utils/kweather: -frameworks/kf5umbrella
Later in the build process, kirigami
also fails. We found out that kirigami
has a working Qt6 CI, so we open one of the (succeeded pipeline jobs)[https://invent.kde.org/frameworks/kirigami/-/jobs/508706] to see which option needs to be enabled for Qt6.
A look at the top of the raw log shows that the calling command is
[32;1m$ python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux --extra-cmake-args=-DBUILD_WITH_QT6=ON --extra-cmake-args=-DEXCLUDE_DEPRECATED_BEFORE_AND_AT=5.94.0 --extra-cmake-args=-DQT_MAJOR_VERSION=6[0;m
So we copy the cmake options to our KDESRC-BUILD config file.
options kirigami
cmake-options -DBUILD_WITH_QT6=ON --extra-cmake-args=-DEXCLUDE_DEPRECATED_BEFORE_AND_AT=5.94.0 --extra-cmake-args=-DQT_MAJOR_VERSION=6
end options
For projects that a have working Qt6 CI, it is always easier to copy the CI commands than to try to debug it yourself.
You may wonder why kirigami
as a KDE framework still needs manual intervention to build on Qt6? Well, when the KDE developers ported a framework to Qt6, they added required option to the (kf6-qt6 config files in KDESRC-BUILD)[https://invent.kde.org/sdk/kdesrc-build/-/blob/master/kf6-frameworks-build-include]. As for kirigami
, it iss still in the process of being ported (but it compiles on Qt6). So if a framework doesn’t work right away, it either means that it is deprecated (kemoticon) or hasn’t been fully ported.
The End
To build app on Qt6 with KDESRC-BUILD, you should:
- change KDESRC-BUILD config file
- apply cmake options on dependencies that failed to build
- change your app’s cmake file to make it Qt6 compatible
Since Kirigami has not yet been fully ported to Qt6, KWeather crashes on startup even though it can be built successfully on Qt6. But this should be a pretty complete example of how to build KDE app on Qt6 with KDESRC-BUILD.
Resource
- https://invent.kde.org/sysadmin/repo-metadata/-/merge_requests/112 MR to fix dependencies for KWeather and KWeatherCore
- https://invent.kde.org/libraries/kweathercore/-/commit/43050956e1d822e18f870189e654605ddc81e793 commit to make KWeatherCore Qt6 compatible