Debian Qt Toolchain installation

From Variscite Wiki
Warning: This page is designed to be used with a 'release' URL parameter.

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:

  1. Visit variwiki.com
  2. Select your SoM
  3. Select the software release


DART-MX8M-PLUS - Debian Qt6.4.0 Toolchain Installation

Introduction

To generate the Qt toolchain, we must build the Qt framework for the host and the target.

We will deal with several folders during the Qt toolchain generation. To keep track, a short summary of the relevant folders and their purpose:

~/debian_imx8mp-var-dart/rootfs Folder of the rootfs created by the Debian build script
~/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/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

Ubuntu 20.04 installation

To setup the Debian build environment, follow steps 1 & 3 of the Debian Build Release guide and build a complete Debian

Additionally, the following packages are needed for the Qt toolchain generation:

$ 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 Cross Compiler:

$ sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

Next, we will need to update cmake manually to 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 .