Cross compilation with Nvidia Jetson Xavier NX (aarch64)
-
I am trying to build Qt 6.4.0 for cross compiling in a Ubuntu 22.04.1 LTS (x86_64) host for an NVIDIA jetson xavier nx (aarch64 with armv8).
For this, I am following the tutorial here, adapting it as much as I can for my case: https://wiki.qt.io/Cross-Compile_Qt_6_for_Raspberry_Pi
I am using the linaro toolchain gcc-linaro-7.5.0-2019 with which I have been able to compile a "hello world" c application and deploy it in the jetson xavier ng.
Current folders are created in my machine:
- qt5: cloned copy of the github repository for version 6.4.0, as indicated in the tutorial above
- qt-host: qt compiled for the host machine
- qthost-build: build files for the qt compilation for the host machine
- qt-jxavier: qt compiled for the target machine
- qtjxavier-build: build files for the qt compilation for the target machine
- jxavier-sysroot: sysroot files from the target machine
When I try to configure the qt5 project to be built for my aarch64 architecture under the qtxavier-build folder, I use the following command (modified from the tutorial above):
../qt5/configure -release -opengl es2 -nomake examples -nomake tests -qt-host-path $HOME/src/qt/qt-host -extprefix $HOME/src/qt/qt-jxavier -prefix /usr/local/qt6 -device linux-jetson-xavier-g++ -device-option CROSS_COMPILE=$HOME/src/linaro/bin/aarch64-linux-gnu- -- -DCMAKE_TOOLCHAIN_FILE=$HOME/src/qt/jxaviertoolchain.cmake -DQT_FEATURE_xcb=ON -DFEATURE_xcb_xlib=ON -DQT_FEATURE_xlib=ON -Wno-devI am getting errors in the configuration process that look like:
Target "XXXX" links to target "GLESv2::GLESv2" but the mkspecs/ target was not found. Perhaps a find_package() call is missing for an IMPORTED target, or an ALIAS target is missing?I have created the following toolchain.cmake
cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR aarch64) set(TARGET_SYSROOT /home/xxx/src/qt/jxavier-sysroot) 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 /home/xxx/src/linaro/bin/aarch64-linux-gnu-gcc) set(CMAKE_CXX_COMPILER /home/xxx/src/linaro/bin/aarch64-linux-gnu-g++) 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(Qt6OpenGL_FOUND TRUE) 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)I have also created my own folder inside qt5/qtbase/mkspecs/devices , which has been copied and modified from the existing folder linux-jetson-tx1-g++, where I have changed the qmake.conf file as follows:
# # qmake configuration for the Jetson Xavier boards running Linux For Tegra # # Note that this environment has been tested with X11 only. # # A typical configure line might look like: # configure \ # -device linux-jetson-tx1-g++ \ # -device-option CROSS_COMPILE=/opt/gcc-linaro-5.3.1-2016.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- \ # -sysroot /opt/Linux_for_Tegra/rootfs # # Note that this builds for GLX + OpenGL. To use EGL + OpenGL ES instead, pass # -opengl es2 and ensure the rootfs has the headers (rootfs/usr/include/EGL, # GLES2, GLES3), which may not be the case out of the box. # # Check the configure output carefully, some features may be disabled due to the # rootfs not having the necessary dev files. # # If getting cryptic linker errors from static libs like libm.a, check that the # symlinks libm.so, libz.so, etc. under rootfs/usr/lib/aarch64-linux-gnu are not # broken. If they are, due to using absolute paths, change them so that they are # relative to rootfs. include(../common/linux_device_pre.conf) QMAKE_INCDIR_POST += \ $$[QT_SYSROOT]/usr/include \ $$[QT_SYSROOT]/usr/include/aarch64-linux-gnu QMAKE_LIBDIR_POST += \ $$[QT_SYSROOT]/usr/lib \ $$[QT_SYSROOT]/lib/aarch64-linux-gnu \ $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu QMAKE_RPATHLINKDIR_POST += \ $$[QT_SYSROOT]/usr/lib \ $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu \ $$[QT_SYSROOT]/lib/aarch64-linux-gnu # Added line as requested in the comments above QMAKE_INCDIR_EGL = $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu/tegra-egl #Not sure if this line really does something or not # This is, as far as I understand, where the libraries for GLES2 reside QMAKE_INCDIR_GLES2 = $$[QT_SYSROOT]/usr/lib/aarch64-linux-gnu/ DISTRO_OPTS += aarch64 COMPILER_FLAGS += -march=armv8-a EGLFS_DEVICE_INTEGRATION = eglfs_kms_egldevice include(../common/linux_arm_device_post.conf) load(qt_config)