Page 1 of 1

Porting Qt to your OS

Posted: Mon Aug 26, 2024 3:07 am
by mohammedisam
I want to share my notes and lessons learned from porting Qt-5.12 to my OS (https://github.com/moisam/laylaos). Please note this is quite different to porting Qt6, which I haven't ventured into yet.

To begin with, it is not an easy task. The target OS must have a working GUI backend to allow you to build Qt on top of it.

You need to port some essential libraries to your OS before trying to port Qt (apart from the obvious, i.e. a hosted compiler, a working libc, ...). Most of these are optional but will make your life easier if you have them, and they are easy to port. These are fontconfig, freetype, harfbuzz, zlib, libjpeg, libpng and gstreamer. I have just ported OpenSL-soft to use as my sound backend, and Qt is able to detect and use it (I will add this in the next release).

My GUI library uses a simple client/server model with a flat window theme, but it has the basic components, e.g. creating and destroying windows, resizing windows, showing/hiding windows, sending events to applications and serving their requests, etc. These are the basic things Qt needs. Your GUI library might provide more functionality (e.g. buttons, textboxes, and all the bells and whistles), but this is not strictly needed as Qt uses its own implementation of GUI widgets. You can go a step further and make Qt use your widgets to give Qt applications a "native" look, but I haven't got there yet.

Qt source tree is surprisingly well-structured and it is clear the designers have put a lot of thought into separating the OS-dependent layer from the rest of the code (in what they call the Qt Platform Abstraction or QPA), making porting much easier than other cross platform toolkits. Most of your OS plugin code will go into this folder:

Code: Select all

qtbase/src/plugins/platforms/YOUR_OS/
With some modifications made to the configuration and qmake files (for example, you need to create a new qmake.conf file for your OS. Strictly speaking, this is a target platform as far as Qt is concerned). The basic C++ classes you need to implement as part of your Qt platform integration plugin are those to handle window operations, mouse cursors, screens (I have one default screen and this should do), window buffers (where Qt draws window contents), clipboard (optional), and platform integration. My client applications need to poll the server for events, so for each application I create an event thread to do the polling. I placed the code in a separate "event looper" class.

Once you sorted out your source code, you can begin to build Qt. The build process itself is straightforward but a bit tricky. QMake needs to be built by the host (i.e. build machine) compiler to create an executable to be run on the host, while the rest of the code will be compiled using your target compiler (i.e. cross compiler). It took some trial and error but I got it working eventually. I custom-create a qmake.conf file for my cross compilation (https://github.com/moisam/laylaos/blob/ ... ke_conf.sh), and then use this in my build script (https://github.com/moisam/laylaos/blob/ ... 5/build.sh). You can see the changes I made to Qt code, as well as the new files I created to add my OS plugin in my ports folder (https://github.com/moisam/laylaos/tree/main/ports/Qt5).

I am still testing my port using Qt's own examples (there are lots!). Most are working, save for some (e.g. the multimedia examples are a bit tricky and they have external dependencies, especially GStreamer, which need more work). I have to point out that I have left qtwebengine out of the process as it is known to be difficult to port and needs a better working network stack than I currently have.

I hope this helps someone else. Thoughts and comments are welcome.

P.S.: If someone else is interested, I am more than happy to post a more detailed tutorial (or a Wiki page perhaps if more people are interested?).

Cheers,

Re: Porting Qt to your OS

Posted: Mon Sep 30, 2024 6:03 am
by Dennisbonke
In my experience, porting Qt6 is significantly less painful than Qt5. Mostly because there's no need to think or deal with qmake anymore, as the build system uses cmake (I believe qmake might be going away completely for Qt7?). Qt6 is also a lot friendlier to disable parts for, with a few configure switches, one can disable all the GUI and network and dbus and sql stuff and leave just core (and a few minor side items) enabled. You do need host tooling, but that's a one time timesync (on every upgrade of Qt6 that you port, but it is what it is). If you're interested, the Qt6 patch can be found here (https://github.com/managarm/bootstrap-m ... port.patch) and the recipe is here (https://github.com/managarm/bootstrap-m ... l#L85-L214).

You also mention qtwebengine. That's not just a better network stack (at least under Qt6, but pretty sure this holds for Qt5.12). QtWebengine requires chromium and itself is just a wrapper using that. I've tried compiling it, it's about 75000 - 80000 targets (it compiles the entire blink web engine twice) and it's a mess. I also tried chromium itself (not in the wrapper) and you don't want to touch that either. It's a giant mess of configure flags that aren't documented (not for cross compilation that is) and it took me a good few weeks of working on it daily (sometimes just letting it run for hours) to even get somewhere. Especially in debug mode don't even try it with the default linker, use mold. Even then, all I got was some local html test page, then it bitrotted. If you need a browser, WebKitGTK MiniBrowser is significantly easier (but still a big task!).