Porting Qt to your OS
Posted: Mon Aug 26, 2024 3:07 am
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:
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,
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/
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,