Getting started with QT, without the nonsense
At work I have recently (yesterday) ended working on a big project and I am now waiting for a new assignment. While I wait, I decided that I should take some time to learn something that could be useful both at work and for my personal projects. After some thought, I settled on QT development with C++.
Any tutorial on this topic tells you to start by downloading QT Creator, an full-blown IDE, and set up a new project from there. In a few clicks you’ll have a couple of source code files and a CMakeLists.txt full of CMake magic. Ready to go!
But there is a problem. I don’t like full-blown IDEs (although admittedly QT Creator seems quite snappy), and I don’t like being locked into specific tools such as CMake. I tried to look online how to set up a QT project without these, but I could not find anything, so I had to figure it out on my own. And then I wrote this post so you don’t have have to waste your time like I did :)
You can find the source code for this tiny project here (or here) if you have bad tase and prefer github over my self-hosted git instance. If you just want to try it out you can run, from the project’s main folder:
make && run
But keep reading if you want to understand how this works!
Requirements
- A C++ compiler (tested with GCC 14.2.1 and Clang 19.1.7, both on Linux-x86_64)
- QT libraries and headers
- The QT development tools
moc
anduic
On Fedora Linux they are contained in the qt6-qtbase-devel
package.
I have not tested this on other operating systems.
Explanation
Following the most basic QT Creator template, there are 4 source code files:
main.cpp
: the main source filemainwindow.h
: the header file for the main window of the applicationmainwindow.cpp
: the C++ source for the main windowmainwindow.ui
: the UI file with an XML description of the main window
The compilation is done in 3 steps:
- Pre-process
mainwindow.h
withmoc
to obtainmoc_mainwindow.cpp
- Compile
mainwindow.ui
withuic
to obtainui_mainwindow.h
- Compile the C++ files, including
moc_mainwindow.cpp
The Makefile
implements these three steps.
The first two steps are straightforward: first you need to locate the
moc
and uic
commands. They are usually in the QT installation
folder - for example I have them in /usr/lib64/qt/libexec
. Then run:
/usr/lib64/qt/libexec/moc mainwindow.h > moc_mainwindow.cpp
/usr/lib64/qt/libexex/uic mainwindow.ui > ui_mainwindow.h
These steps can be skipped if one prefers to write the moc_
and ui_
files directly, removing the dependency on the two tools.
For the last step, one needs to include the header files and link with the QT libraries.
On my system the header files are in /usr/include/qt6
. This means I
need to add the option -I /usr/include/qt6
to my g++
command. This
project also requires headers contained in a subfolder of this,
so I will add a second -I
option (see the full command below).
As for the shared libraries, in my case they are installed in a system
folder that is scanned by default by the linker, so I don’t have to
specify the path. We need the files libQt6Widgets.so
, libQt6Core.so
and libQt6Gui.so
, which we can include with
-lQt6Widgets -lQt6Core -lQt6Gui
. If your linker does not find them,
locate them and include their folder with -L /path/to/the/folder
.
So the command for step 3 becomes:
g++ main.cpp mainwindow.cpp moc_mainwindow.cpp \
-I /usr/include/qt6 -I /usr/include/qt6/QtWidgets \
-lQt6Widgets -lQt6Core -lQt6Gui
-o run
And finally you can enjoy your new app:
./run
Update 2025-04-07 - now with AI!
When I shared this post on LinkedIn, I asked if anyone could prompt an LLM to build a QT app without QT Creator or CMake. A colleague did, and the catbot’s (pun intended) response can be found here.
This solution is different from the one I found. The bot opted for using
qmake, another tool bundled
with QT, like moc and uic. This tool reads a .pro
file that describes
the project’s structure and build configuration, and it generates a
Makefile
. This method is a bit more black-boxy than the one I found,
but it does not require more external dependencies; I think I might use
this other approach in the future.
The chat bot’s response is great, but it is “only” 99% accurate. Unfortunately this means that if one blindly follows these instructions, they won’t get a working QT application. The problem is with the commands:
qmake -project
qmake
The first one is completely useless, and actually prevents the project
from being built by generating a second project file. If one simply
ignores the qmake -project
line, the instructions become correct.
This story is quite insightful: the chat bot gave me instructions that are almost correct (so technically they are incorrect). With my experience (a whole 5 hours of CV-worthy QT development) I was able to fix these instructions easily in a couple of minutes, but someone without the same experience would have probably struggled for much longer.