summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-11-16 17:04:14 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-11-18 12:45:24 +0100
commitf06a3ec3aed6ff09322d6feb5938d47528a7b44f (patch)
treec9da212b62207109529035d607b69bdf5b00fcfd
parentda84e3c2796d3e897c17919316c41ebdb150add6 (diff)
downloadqtdoc-f06a3ec3aed6ff09322d6feb5938d47528a7b44f.tar.gz
Update Embedded Linux configure docs
Change-Id: Ia9e5c2114c0fc0902f6cc350387bc9b60500e851 Fixes: QTBUG-88369 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--doc/src/platforms/configure-linux-device.qdoc367
-rw-r--r--doc/src/platforms/emb-linux.qdoc3
-rw-r--r--doc/src/platforms/supported-platforms.qdocinc9
3 files changed, 331 insertions, 48 deletions
diff --git a/doc/src/platforms/configure-linux-device.qdoc b/doc/src/platforms/configure-linux-device.qdoc
index 06955f88..9354ad5e 100644
--- a/doc/src/platforms/configure-linux-device.qdoc
+++ b/doc/src/platforms/configure-linux-device.qdoc
@@ -30,56 +30,331 @@
\title Configure an Embedded Linux Device
\brief Provides information about how to configure an Embedded Linux device in Qt.
- Building Qt for a given device requires a toolchain and a \c sysroot. Additionally, some
- devices require vendor-specific adaptation code for EGL and OpenGL ES 2.0 support. This is
- not relevant for non-accelerated platforms, such as those that use the LinuxFB plugin, which is
- meant for software-based rendering only.
-
- The \e qtbase/mkspecs/devices directory contains configuration and graphics adaptation code for
- a number of devices. For example, the \c linux-rasp-pi2-g++ mkspec contains build settings such
- as the optimal compiler and linker flags for the \l{http://www.raspberrypi.org}{Raspberry Pi 2}
- device. The mkspec also contains information about either an implementation of the \e eglfs
- hooks (vendor-specific adaptation code), or a reference to the suitable \e eglfs device
- integration plugin. The device is selected through the \l{Qt Configure Options}{configure}
- tool's \c -device parameter. The name that follows after this argument must, at least
- partially, match one of the subdirectories under \e devices.
-
- The following is an example configuration for the Raspberry Pi 2. For most Embedded Linux
- boards, the configure command looks similar:
+ Cross-compiling Qt for a given device requires a \b toolchain and a \b sysroot. The
+ toolchain is expected to contain a version of gcc, or another compiler, and associated
+ tools built for cross-compilation. This means these tools run on the \b host system
+ (typically x64), while producing binaries for the target architecture (for example, 32
+ or 64 bit ARM). The sysroot contains the headers and libraries for the target system,
+ allowing compiling and linking libraries and applications on the host.
+
+ This overview page describes to the generic approach, where no distribution building
+ systems, such as Yocto or Buildroot, are used. It is always possible to cross-compile
+ and deploy Qt onto a device as long as a suitable toolchain and sysroot are available.
+
+ \warning This page can only provide a generic, high-level overview. There are a
+ vast number of details that can vary depending on the build environment, the
+ target device, and the toolchain. When in doubt, refer to your system
+ integrator. For pre-built reference images and SDKs, refer to the
+ \l{http://doc.qt.io/QtForDeviceCreation}{Qt for Device Creation} offering.
+
+ When running Qt-based applications without a windowing system, such as X11 or Wayland,
+ some devices require vendor-specific adaptation code for EGL and OpenGL ES
+ support. This is provided in form of backends for the EGLFS platform plugin. This is
+ not relevant for non-accelerated platforms, such as those that use the LinuxFB
+ platform plugin, which is meant for software-based rendering only. As of Qt 6, many
+ embedded systems use \l{https://en.wikipedia.org/wiki/Direct_Rendering_Manager}{drm}
+ to set a video mode, manage display connectors and graphical surfaces. For example, an
+ NXP i.MX8-based device or a Raspberry Pi 4 will use this approach, and therefore the
+ most commonly used backend for EGLFS is \b eglfs_kms, which enables EGL and OpenGL
+ ES based rendering with \c drm, using \c gbm for surface and buffer management. Older
+ devices, such as the NXP i.MX6, will continue to use the legacy, GPU vendor-specific
+ approach to connect EGL window surfaces to the framebuffer, using dedicated eglfs
+ backends, such as \c eglfs_viv.
+
+ \note Be aware that Qt is just one component in the software stack for an embedded
+ device. Especially when accelerated graphics are involved, Qt expects a functional
+ graphics stack, with an appropriate configuration for the userspace and kernel
+ components, such as the display driver. These components are outside of Qt's domain,
+ and it is the system integrator's responsibility to ensure the base system is fully
+ functional and optimal, including accelerated graphics.
+
+ For further information on graphics and input configuration for Embedded Linux
+ systems, refer to \l{Qt for Embedded Linux}.
+
+ \section1 Toolchain Files versus Device Makespecs
+
+ In Qt 5, you would typically use a device spec under the \e qtbase/mkspecs/devices
+ directory. These contain the appropriate compiler and linker flags for a certain
+ device, also making sure the correct EGL and OpenGL ES libraries are picked up, in
+ case they are in a non-standard location in the sysroot.
+
+ For example, you could have configured a Qt 5 build for a Raspberry Pi 2 with a
+ configure command like the following:
\badcode
./configure -release -opengl es2 -device linux-rasp-pi2-g++ -device-option CROSS_COMPILE=$TOOLCHAIN/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot $ROOTFS -prefix /usr/local/qt5
\endcode
- The most important parameters are \c -device and \c -sysroot. By specifying \c -sysroot, the
- include files and libraries used by \c {configure}'s feature detection tests, as well as Qt
- itself, are taken from the specified location, instead of the host PC's standard locations.
- Consequently, installing development packages on the host machine has no relevance. For
- example, to get \c libinput support, it is not sufficient or necessary to have the \c libinput
- development headers and libraries installed on the host environment. Instead, the headers and
- the libraries for the target architecture, such as ARM, must be present in the \c sysroot.
-
- \c pkg-config is supported also when performing cross-compilation. \c configure automatically
- sets \c PKG_CONFIG_LIBDIR to make \c pkg-config report compiler and linker settings based on
- the \c sysroot instead of the host machine. This usually functions well without any further
- adjustments. However, environment variables such as \c PKG_CONFIG_PATH must be unset for the
- host machine before running \c configure. Otherwise, the Qt build may attempt to use
- inappropriate headers and libraries from the host system.
-
- Specifying \c -sysroot results in automatically setting the \c --sysroot argument when invoking
- the compiler. In some cases this is not desirable and can be disabled by passing
- \c -no-gcc-sysroot to \c configure.
-
- \c -prefix, \c -extprefix, and \c -hostprefix control the intended destination directory of the
- Qt build. In the above example the ARM build of Qt is expected to be placed in
- \c{/usr/local/qt5} on the target device. Note that running \c{make install} does not deploy
- anything to the device. Instead, the \c install step targets the directory specified by
- \c extprefix which defaults to \c sysroot + \c prefix and is therefore optional. However, in
- many cases "polluting" the sysroot is not desirable and thus specifying \c -extprefix becomes
- important. Finally, \c -hostprefix allows separating host tools like qmake, rcc, uic from the
- binaries for the target. When given, such tools will be installed under the specified directory
- instead of \c extprefix.
-
- For more information, see \l {Qt Configure Options}.
+ With Qt 6 and CMake, this approach is \b{no longer sufficient} on its own. Rather, a
+ \l{https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html}{CMake toolchain
+ file} must be provided before configuring can happen. It is in this file where
+ customization with regards to compiler and linker flags, and toolchain and sysroot
+ specific quirks, happens.
+
+ In the below sections we will present a toolchain file that can be used in many cases,
+ with minimal customization. It is based on the approach presented in
+ \l{https://www.qt.io/blog/standalone-boot2qt-/-yocto-sdk-cmake-toolchain}{this blog
+ post}.
+
+ \note The toolchain file presented below is an example, that will often need further
+ customizations for a given device. Users and system integrators are also free to
+ create their own toolchain files in any way they see fit.
+
+ While CMake is the only supported build system for building Qt itself, applications
+ may still be built using \c qmake in Qt 6.0. In order to get a \c qmake setup that is
+ functional with cross-compilation, one will need to specify some of the legacy
+ arguments to CMake or to configure.
+
+ \section1 Host Tools
+
+ Cross-compiling Qt requires a host build of Qt being available. During the build,
+ tools such as \c moc, \c rcc, \c qmlcachegen, \c qsb, and others, are invoked from
+ there. For example, if one cross-compiles for ARM on an x64 machine, a local x64 build
+ of the same Qt version must be made available first. The path to this Qt build will be
+ passed to configure or cmake.
+
+ \section1 Configuring Qt
+
+ Let's assume that the following are available:
+
+ \list
+ \li a toolchain and sysroot under \c{$HOME/rpi-sdk},
+ \li a checkout of Qt, at minimum the qtbase module, under \c{$HOME/qt-cross},
+ \li a host build of Qt in \c{$HOME/qt-host}.
+ \endlist
+
+ In addition, the following must be decided before configuring:
+
+ \list
+
+ \li Where will the Qt build be installed on the local system once the build completes?
+ In the example we will use \c{$HOME/qt6-rpi}.
+
+ \li Where will the Qt build be deployed on the device? In the example we will use
+ \c{/usr/local/qt6}.
+
+ \endlist
+
+ In the example we are going to use a Raspberry Pi 4 SDK (toolchain+sysroot) generated
+ via Yocto, but the instructions here are completely generic, with no dependency on
+ Yocto. The steps are the same with any other toolchain and sysroot, once the toolchain
+ file is updated with the correct cross compiler and other paths.
+
+ After creating and switching to a \c build directory:
+
+ \badcode
+ $HOME/qt-cross/qtbase/configure -release -opengl es2 -nomake examples -nomake tests \
+ -qt-host-path $HOME/qt-host \
+ -extprefix $HOME/qt6-rpi \
+ -prefix /usr/local/qt6 \
+ -- -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake \
+ -DQT_BUILD_TOOLS_WHEN_CROSSCOMPILING=ON
+ \endcode
+
+ In practice this configure command is equivalent to the following direct CMake call:
+
+ \badcode
+ cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DINPUT_opengl=es2 -DBUILD_EXAMPLES=OFF -DBUILD_TESTING=OFF \
+ -DQT_HOST_PATH=$HOME/qt-host \
+ -DCMAKE_STAGING_PREFIX=$HOME/qt6-rpi \
+ -DCMAKE_INSTALL_PREFIX=/usr/local/qt6 \
+ -DCMAKE_TOOLCHAIN_FILE=$HOME/qt-cross/toolchain.cmake \
+ -DQT_BUILD_TOOLS_WHEN_CROSSCOMPILING=ON \
+ $HOME/qt-cross/qtbase
+ \endcode
+
+ Given the appropriate toolchain file, this is sufficient to generate a Qt build that
+ then allows applications to be built using CMake. To enable applications to be built
+ with \c qmake as well, the Qt 5 style device spec and device options must be
+ specified, in addition to all arguments shown above:
+
+ \badcode
+ $HOME/qt-cross/qtbase/configure ...
+ ...
+ -device linux-rasp-pi4-v3d-g++ \
+ -device-option CROSS_COMPILE=$HOME/rpi_sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi- \
+ -device-option DISTRO_OPTS="hard-float" \
+ ...
+ \endcode
+
+ Enabling \c{QT_BUILD_TOOLS_WHEN_CROSSCOMPILING} is optional. If only the Qt libraries,
+ and no associated tools, are desired for the target device, then it can be left
+ out. However, enabling it is often a good idea, because it will lead to building
+ binaries of tools meant to be run on the target device, such as \c qml, \c qmlscene,
+ or \c qmlpreview.
+
+ \note When \c{QT_BUILD_TOOLS_WHEN_CROSSCOMPILING} is enabled, target binaries of tools
+ like \c qmake will get installed to the staging location. Therefore, if \c qmake is
+ used to build applications, call the \c{host-qmake} script instead.
+
+ Once configuration completes without errors, run \c{cmake --build . --parallel} to
+ build. Once built, run \c{cmake --install .} to install the results to
+ \c{$HOME/qt6-rpi}. From there the Qt build can be deployed to the device by using
+ rsync, scp, or another method.
+
+ If building individual Qt modules, one can use the \c qt-configure-module script from
+ the \c bin directory of the staging location (\c{$HOME/qt6-rpi} in the example) to
+ configure additional modules, such as qtdeclarative, qtquick3d, and so on. They can
+ then be built using \c{cmake --build .} and installed to the staging location by
+ running \c{cmake --install .}
+
+ \note Before starting the build, always inspect the output of the configuration step
+ carefully: does it have all the expected features enabled? Making a build and
+ deploying it to the device is futile if essential features are not enabled at
+ configuration time.
+
+ For example, when accelerated graphics via OpenGL is desired, pay extra attention to
+ the following features:
+
+ \badcode
+ EGL .................................... yes
+ OpenGL:
+ Desktop OpenGL ....................... no
+ OpenGL ES 2.0 ........................ yes
+ OpenGL ES 3.0 ........................ yes
+ ...
+ evdev .................................. yes
+ libinput ............................... yes
+ ...
+ EGLFS .................................. yes
+ EGLFS details:
+ EGLFS OpenWFD ........................ no
+ EGLFS i.Mx6 .......................... no
+ EGLFS i.Mx6 Wayland .................. no
+ EGLFS RCAR ........................... no
+ EGLFS EGLDevice ...................... yes
+ EGLFS GBM ............................ yes
+ EGLFS VSP2 ........................... no
+ EGLFS Mali ........................... no
+ EGLFS Raspberry Pi ................... no
+ EGLFS X11 ............................ no
+ LinuxFB ................................ yes
+ \endcode
+
+ With the Raspberry Pi 4 example, we expect that EGL, OpenGL ES and \c{EGLFS GBM} are
+ all reported as \c yes, otherwise the EGLFS platform plugin and its \b eglfs_kms
+ backend will not be functional on the device. For getting function mouse, keyboard,
+ and touch input, either \c evdev or \c libinput must be enabled.
+
+ Similarly, if X11 is planned to be used as the (or one of the) windowing systems on
+ the device, then ensure the xcb and X11 related features are marked as \c yes.
+
+ \section1 An Example Toolchain File
+
+ We will assume there is a sysroot and toolchain available under \c{$HOME/rpi-sdk}. \c
+ TARGET_SYSROOT and \c CROSS_COMPILER must be adjusted to the toolchain and sysroot in
+ use. The example here is only suitable for one specific, Yocto-generated SDK. The same
+ is true for \c CMAKE_C_COMPILER and \c CMAKE_CXX_COMPILER.
+
+ We do not rely on any wrapper scripts that would provide environment variables such as
+ PKG_CONFIG_*. Rather, the path to the .pc files is specified in the toolchain file. It
+ is likely that another sysroot will need adjustments in \c PKG_CONFIG_LIBDIR. For
+ example, with a sysroot generated from a Raspberry Pi OS (formerly Raspbian) image one
+ would use \c{/usr/lib/arm-gnueabihf/pkgconfig} instead.
+
+ The compiler and linker flags are not necessary optimal in the example. Adjust them as
+ necessary for the target device.
+
+ For further information on the CMake specifics in the example toolchain file, refer to
+ \l{https://www.qt.io/blog/standalone-boot2qt-/-yocto-sdk-cmake-toolchain}{this blog
+ post} and \l{https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html}{the
+ CMake documentation}.
+
+ \badcode
+cmake_minimum_required(VERSION 3.18)
+include_guard(GLOBAL)
+
+set(CMAKE_SYSTEM_NAME Linux)
+set(CMAKE_SYSTEM_PROCESSOR arm)
+
+set(TARGET_SYSROOT /home/user/rpi-sdk/sysroots/cortexa7t2hf-neon-vfpv4-poky-linux-gnueabi)
+set(CROSS_COMPILER /home/user/rpi-sdk/sysroots/x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi)
+
+set(CMAKE_SYSROOT ${TARGET_SYSROOT})
+
+set(ENV{PKG_CONFIG_PATH} "")
+set(ENV{PKG_CONFIG_LIBDIR} ${CMAKE_SYSROOT}/usr/lib/pkgconfig:${CMAKE_SYSROOT}/usr/share/pkgconfig)
+set(ENV{PKG_CONFIG_SYSROOT_DIR} ${CMAKE_SYSROOT})
+
+set(CMAKE_C_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-gcc)
+set(CMAKE_CXX_COMPILER ${CROSS_COMPILER}/arm-poky-linux-gnueabi-g++)
+
+set(QT_COMPILER_FLAGS "-march=armv7-a -mfpu=neon -mfloat-abi=hard")
+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)
+
+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()
+ \endcode
+
+ \section1 Building Applications for the Target Device
+
+ Once the Qt build is done and installed to the staging location, examples or
+ applications can be built.
+
+ With CMake, use the generated \c qt-cmake script in the \c bin directory of the
+ staging location (\c{$HOME/qt6-rpi} in the example) to configure, then run \c
+ ninja. For example:
+
+ \badcode
+ $HOME/qt6-rpi/bin/qt-cmake .
+ cmake --build .
+ \endcode
+
+ The resulting application binary can then be deployed to the device. Using the \c
+ qt-cmake helper script is convenient, because the script ensures the toolchain file
+ that was used for building Qt is loaded, so there is no need to repeatedly specify it
+ for each application.
+
+ Unlike for Qt itself, building applications with qmake is still supported in Qt 6.0,
+ as long as a suitable device spec is available, and the appropriate legacy arguments
+ were passed to CMake or configure when configuring Qt. If this is all true, then
+ running \c qmake and \c make will also generate an application binary for the target
+ device.
+
+ \section1 Defaults for Platform Plugins and EGLFS
+
+ Once configured, a default platform plugin is chosen. This is used when launching an
+ application without the \c{-platform} argument and without having the \c
+ QT_QPA_PLATFORM environment variable set.
+
+ Similarly, the EGLFS platform plugin has multiple backends. The default is chosen
+ based on availability and a pre-defined priority order. If drm and gbm are available,
+ the default will be the \b eglfs_kms backend. This can always be overridden at runtime
+ by setting the \c QT_QPA_EGLFS_INTEGRATION environment variable.
+
+ To change these defaults for the build, without having to force a specific value at
+ run time, the following to CMake cache variables are available once CMake has been run
+ once:
+
+ \list
+ \li \c QT_QPA_DEFAULT_PLATFORM (\c STRING) - The name of the default platform plugin.
+ \li \c QT_QPA_DEFAULT_EGLFS_INTEGRATION (\c STRING) - The default EGLFS backend.
+ \endlist
+ For more information on configuring Qt, see \l {Qt Configure Options}.
*/
diff --git a/doc/src/platforms/emb-linux.qdoc b/doc/src/platforms/emb-linux.qdoc
index 583f3d26..17e92b51 100644
--- a/doc/src/platforms/emb-linux.qdoc
+++ b/doc/src/platforms/emb-linux.qdoc
@@ -45,6 +45,9 @@
is a superior solution; multi-process use cases are supported through
\l{Qt Wayland Compositor}{Wayland}.
+ See \l{Configure an Embedded Linux Device} for an overview of configuring Qt
+ for cross-compilation using an Embedded Linux toolchain.
+
\section1 Platform Plugins for Embedded Linux Devices
\target embedded eglfs
diff --git a/doc/src/platforms/supported-platforms.qdocinc b/doc/src/platforms/supported-platforms.qdocinc
index 0052c6a6..b79bb5cb 100644
--- a/doc/src/platforms/supported-platforms.qdocinc
+++ b/doc/src/platforms/supported-platforms.qdocinc
@@ -113,8 +113,13 @@
\section1 Embedded Platforms
//! [embedded]
-Please consult the \l {http://doc.qt.io/QtForDeviceCreation}{Qt for Device Creation}
-documentation for embedded platform support.
+\section2 \l{Qt for Embedded Linux}{Embedded Linux}
+
+Refer to \l{Configure an Embedded Linux Device} for information on generic
+cross-compilation of Qt for Embedded Linux devices.
+
+For further embedded platform support, please consult the
+\l{http://doc.qt.io/QtForDeviceCreation}{Qt for Device Creation} documentation.
//! [embedded]