Debian Qt Toolchain installation
This page is using the default release mx8mp-debian-bullseye-5.10.52_2.1.0-v1.1.
To view this page for a specific Variscite SoM and software release, please follow these steps:
- Visit variwiki.com
- Select your SoM
- Select the software release
Introduction
Qt is a powerful cross-platform application framework that enables developers to create high-performance applications for various operating systems, including embedded Linux. It provides a comprehensive library of pre-defined components and tools for creating graphical user interfaces, network applications, and more. This guide provides a walkthrough on how to cross-compile Qt for Variscite i.MX8-based SOMs, allow you to compile applications on a host machine and deploy them to the SOM running a Debian image.
The generated Qt toolchain consists of the following:
- qt6-x86_64: Qt installation (headers, libraries, plugins, etc.) for the host architecture
- qt6-mx8mp-debian-11-wayland: Qt installation (headers, libraries, plugins, etc.) for the target architecture
The Qt toolchain with the Cross Compiler and the target sysroot enables Qt application programming from CLI or using the Qtcreator IDE.
You can find a list of useful Qt documentation references in the section: Qt Creator guide
As we're going to deal with several folders, here is a short summary to keep track:
~/debian_imx8mp-var-dart/src/qt6 | Folder for the Qt6 framework sources | |
~/debian_imx8mp-var-dart/src/qt6/.x86_64_build | Build folder for Qt6 host compilation | |
~/debian_imx8mp-var-dart/src/qt6/.mx8mp-debian-11-wayland_build | Build folder for Qt6 target compilation | |
~/debian_imx8mp-var-dart/toolchain/sysroot | Debian sysroot created using the Create a Debian sysroot guide | |
~/debian_imx8mp-var-dart/toolchain/qt6-x86_64 | Installation folder for the Qt6 host variant | |
~/debian_imx8mp-var-dart/toolchain/qt6-mx8mp-debian-11-wayland | Installation folder for the Qt6 target variant |
Setup Host Computer environment
We will create the Qt toolchain in the Debian build environment using a Ubuntu 20.04 machine. Therefore, please follow the steps:
Now, we need to install the packages needed for the Qt toolchain generation, please run the following to install those:
$ sudo apt-get update $ sudo apt-get install -y make build-essential libclang-dev ninja-build gcc git bison python3 gperf pkg-config libfontconfig1-dev \ libfreetype6-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-glx0-dev \ libxcb-keysyms1-dev libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev \ libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev \ libxkbcommon-x11-dev libatspi2.0-dev libgl1-mesa-dev libglu1-mesa-dev freeglut3-dev \ libwayland-dev libwayland-bin libwayland-egl1-mesa libwayland-client0 libwayland-server0 libwayland-cursor0 libgles2-mesa-dev
Next, we will install the Gnu C/C++ Cross Compiler:
$ sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
Finally, we will need to update cmake manually to a newer version:
$ cd ~ $ sudo apt-get remove -y cmake $ wget https://github.com/Kitware/CMake/releases/download/v6.4/cmake-v3.22.0.tar.gz $ tar -zvxf cmake-v3.22.0.tar.gz $ cd cmake-v3.22.0 $ ./bootstrap $ make -j$(nproc) $ sudo make install
Once the installation is done, it is reasonable to double-check the version:
$ cmake --version cmake version v3.22.0
Obtain Qt6 framework sources
Download the Qt6 sources from the official Qt download archive:
$ cd ~/debian_imx8mp-var-dart/src $ wget https://download.qt.io/archive/qt//6.4.0/single/qt-everywhere-src-6.4.0.tar.xz
And untar the archive:
$ tar -xf qt-everywhere-src-6.4.0.tar.xz qt6 $ cd ..
The Qt6 framework sources are now located at ~/debian_imx8mp-var-dart/src/qt6.
Compile Qt6 for the host
Create the build and installation folder:
$ mkdir -p ~/debian_imx8mp-var-dart/toolchain/qt6-x86_64 $ mkdir -p ~/debian_imx8mp-var-dart/src/qt6/.x86_64_build
Build and install the Qt framework for the host:
$ cd ~/debian_imx8mp-var-dart/src/qt6/.x86_64_build $ cmake ../qt-everywhere-src-6.4.0/ -Wno-dev -GNinja -DCMAKE_BUILD_TYPE=Release -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX=$HOME/debian_imx8mp-var-dart/toolchain/qt6-x86_64 -DBUILD_qtwayland=ON $ cmake --build . --parallel 32 $ cmake --install .
Cross-Compile Qt6 for the target
Create the sysroot
We would need a Debian sysroot with all required libraries to cross-compile the Qt framwork for the target on the host. We will use the build script G_USER_PACKAGES variable to add the needed libraries to the rootfs.
Please follow the … for more information where to find the G_USER_PACKAGES variable, and add:
readonly G_USER_PACKAGES="\
libboost-all-dev libudev-dev libinput-dev libts-dev libmtdev-dev libjpeg-dev libfontconfig1-dev libssl-dev libdbus-1-dev libglib2.0-dev \
libxkbcommon-dev libegl1-mesa-dev libgbm-dev libgles2-mesa-dev mesa-common-dev libasound2-dev libpulse-dev gstreamer1.0-omx libgstreamer1.0-dev \
libgstreamer-plugins-base1.0-dev gstreamer1.0-alsa libvpx-dev libsrtp2-dev libsnappy-dev libnss3-dev "^libxcb.*" flex bison libxslt-dev \
ruby gperf libbz2-dev libcups2-dev libatkmm-1.6-dev libxi6 libxcomposite1 libfreetype6-dev libicu-dev libsqlite3-dev libxslt1-dev \
\
libavcodec-dev libavformat-dev libswscale-dev libx11-dev freetds-dev libsqlite3-dev libpq-dev libiodbc2-dev firebird-dev libgst-dev \
libxext-dev libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev \
libxcb-icccm4 libxcb-icccm4-dev libxcb-sync1 libxcb-sync-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev \
libxcb-randr0-dev libxcb-glx0-dev libxi-dev libdrm-dev libxcb-xinerama0 libxcb-xinerama0-dev libatspi2.0-dev libxcursor-dev libxcomposite-dev libxdamage-dev \
libxss-dev libxtst-dev libpci-dev libcap-dev libxrandr-dev libdirectfb-dev libaudio-dev libxkbcommon-x11-dev \
\
libwayland-dev libwayland-egl1-mesa libwayland-client0 libwayland-server0 libwayland-cursor0 libgles2-mesa-dev
"
This will add the libraries to the Debian rootfs on compile-time during the build. Once Debian has been built, please refer to … to learn how to create the sysroot.
The sysroot should be located at ~/debian_imx8mp-var-dart/toolchain/sysroot and can be used to cross-compile the Qt framework in the next step.
Cross-compile the framework
Create the build and installation folder:
$ mkdir -p ~/debian_imx8mp-var-dart/toolchain/qt6-mx8mp-debian-11-wayland $ mkdir -p ~/debian_imx8mp-var-dart/src/qt6/.mx8mp-debian-11-wayland_build
Create a file, named toolchain.cmake, and locate it at ~/debian_imx8mp-var-dart/src/qt6/.mx8mp-debian-11-wayland_build, with the following content:
cmake_minimum_required(VERSION 3.18)
include_guard(GLOBAL)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(TARGET_SYSROOT <<<TARGET_SYSROOT_PATH>>>)
set(CMAKE_SYSROOT ${TARGET_SYSROOT})
set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:/usr/lib/aarch64-linux-gnu/pkgconfig)
set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/pkgconfig/:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/pkgconfig:${TARGET_SYSROOT}/usr/lib/pkgconfig)
set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
# if you use other version of gcc and g++ than gcc/g++ 9, you must change the following variables
set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc-9)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++-9)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I${TARGET_SYSROOT}/usr/include")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")
set(QT_COMPILER_FLAGS "-march=armv8-a")
set(QT_COMPILER_FLAGS_RELEASE "-O2 -pipe")
set(QT_LINKER_FLAGS "-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_BUILD_RPATH ${TARGET_SYSROOT})
include(CMakeInitializeConfigs)
function(cmake_initialize_per_config_variable _PREFIX _DOCSTRING)
if (_PREFIX MATCHES "CMAKE_(C|CXX|ASM)_FLAGS")
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_INIT "${QT_COMPILER_FLAGS}")
foreach (config DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
if (DEFINED QT_COMPILER_FLAGS_${config})
set(CMAKE_${CMAKE_MATCH_1}_FLAGS_${config}_INIT "${QT_COMPILER_FLAGS_${config}}")
endif()
endforeach()
endif()
if (_PREFIX MATCHES "CMAKE_(SHARED|MODULE|EXE)_LINKER_FLAGS")
foreach (config SHARED MODULE EXE)
set(CMAKE_${config}_LINKER_FLAGS_INIT "${QT_LINKER_FLAGS}")
endforeach()
endif()
_cmake_initialize_per_config_variable(${ARGV})
endfunction()
set(XCB_PATH_VARIABLE ${TARGET_SYSROOT})
set(GL_INC_DIR ${TARGET_SYSROOT}/usr/include)
set(GL_LIB_DIR ${TARGET_SYSROOT}:${TARGET_SYSROOT}/usr/lib/aarch64-linux-gnu/:${TARGET_SYSROOT}/usr:${TARGET_SYSROOT}/usr/lib)
set(EGL_INCLUDE_DIR ${GL_INC_DIR})
set(EGL_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libEGL.so)
set(OPENGL_INCLUDE_DIR ${GL_INC_DIR})
set(OPENGL_opengl_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libOpenGL.so)
set(GLESv2_INCLUDE_DIR ${GL_INC_DIR})
set(GLIB_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libGLESv2.so)
set(GLESv2_INCLUDE_DIR ${GL_INC_DIR})
set(GLESv2_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libGLESv2.so)
set(gbm_INCLUDE_DIR ${GL_INC_DIR})
set(gbm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libgbm.so)
set(Libdrm_INCLUDE_DIR ${GL_INC_DIR})
set(Libdrm_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libdrm.so)
set(XCB_XCB_INCLUDE_DIR ${GL_INC_DIR})
set(XCB_XCB_LIBRARY ${XCB_PATH_VARIABLE}/usr/lib/aarch64-linux-gnu/libxcb.so)
And replace the token <<<TARGET_SYSROOT_PATH>>>
with $HOME/debian_imx8mp-var-dart/toolchain/sysroot
in this file to set the sysroot path properly.
Next, we can cross-compile the Qt framework for the target:
$ cd ~/debian_imx8mp-var-dart/src/qt6/.mx8mp-debian-11-wayland_build $ cmake ../ -GNinja -Wno-dev -DCMAKE_BUILD_TYPE=Release \ -DQT_HOST_PATH=$HOME/debian_imx8mp-var-dart/toolchain/qt6-x86_64 \ -DCMAKE_INSTALL_PREFIX=/usr/local/qt6 \ -DCMAKE_TOOLCHAIN_FILE=$HOME/debian_imx8mp-var-dart/src/qt6/.mx8mp-debian-11-wayland_build/toolchain.cmake \ -DCMAKE_STAGING_PREFIX=$HOME/debian_imx8mp-var-dart/toolchain/qt6-mx8mp-debian-11-wayland \ -DQT_QMAKE_TARGET_MKSPEC=devices/linux-imx8-g++ \ -DQT_BUILD_EXAMPLES=OFF -DQT_BUILD_TESTS=OFF \ -DBUILD_qtwayland=ON \ -DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON \ -DBUILD_qt3d=OFF -DBUILD_qtquick3d=OFF -DBUILD_qtquick3dphysics=OFF $ cmake --build . --parallel $(nproc)
And finally, install it locally on the host at ~/debian_imx8mp-var-dart/toolchain/qt6-mx8mp-debian-11-wayland:
$ cmake --install .