qmake for cross-compiling x86-64 --> armv7
-
Hello,
I'm struggling with the configuration of QtCreator for cross-compiling on a host x86-64 virtual machine to create executable for ARMv7 architecture using compiled (and cross-compiled) sources of Qt6.
Here's what I've done so far:
- Successful compilation of Qt6 sources for my Ubuntu x86-64 virtual machine (example applications run on it smoothly),
- Successful cross-compilation of Qt6 sources for my arm device, and
- Successful cross-compilation (on host machine, using cmake) of an example application; that application also runs ok on my arm device with the previously cross-compiled Qt6 sources.
Now I'd like to push one step forward and make the QtCreator (v6.0.2) to be able to cross-compile for my arm device. I added my gcc/g++ cross compilers to it, but my problem comes from the Qt Versions:
- I can add the host's qmake (or qmake6) as a Qt Version, but it is recognized with x86-64 ABI and thus incompatible with my cross-compilers (arm 32bits) when I create the Kit
- I cannot add the target's qmake nor qmake6 as they are scripts calling the host's qmake6; QtCreator complains "Qmake Not Executable"
- I cannot add the target's qmake (nor qmake6) which I forced to compile with -DQT_FORCE_BUILD_TOOLS=ON as it is cross-compiled for ARM and thus not executable on my virtual machine.
Therefore, I imagine I need a x86-64 qmake which uses arm Qt6 libraries.
I found on https://doc.qt.io/qt-6/configure-linux-device.html the following paragraph: "In order to get a qmake setup that is functional with cross-compilation, one will need to specify some of the legacy arguments to CMake or to configure."
But nothing more than that.
Is there anyone that could tell me how to achieve that? Or maybe the problem is somewhere else (QtCreator version too old)? -
Hello,
I'm struggling with the configuration of QtCreator for cross-compiling on a host x86-64 virtual machine to create executable for ARMv7 architecture using compiled (and cross-compiled) sources of Qt6.
Here's what I've done so far:
- Successful compilation of Qt6 sources for my Ubuntu x86-64 virtual machine (example applications run on it smoothly),
- Successful cross-compilation of Qt6 sources for my arm device, and
- Successful cross-compilation (on host machine, using cmake) of an example application; that application also runs ok on my arm device with the previously cross-compiled Qt6 sources.
Now I'd like to push one step forward and make the QtCreator (v6.0.2) to be able to cross-compile for my arm device. I added my gcc/g++ cross compilers to it, but my problem comes from the Qt Versions:
- I can add the host's qmake (or qmake6) as a Qt Version, but it is recognized with x86-64 ABI and thus incompatible with my cross-compilers (arm 32bits) when I create the Kit
- I cannot add the target's qmake nor qmake6 as they are scripts calling the host's qmake6; QtCreator complains "Qmake Not Executable"
- I cannot add the target's qmake (nor qmake6) which I forced to compile with -DQT_FORCE_BUILD_TOOLS=ON as it is cross-compiled for ARM and thus not executable on my virtual machine.
Therefore, I imagine I need a x86-64 qmake which uses arm Qt6 libraries.
I found on https://doc.qt.io/qt-6/configure-linux-device.html the following paragraph: "In order to get a qmake setup that is functional with cross-compilation, one will need to specify some of the legacy arguments to CMake or to configure."
But nothing more than that.
Is there anyone that could tell me how to achieve that? Or maybe the problem is somewhere else (QtCreator version too old)?@robgu said in qmake for cross-compiling x86-64 --> armv7:
Therefore, I imagine I need a x86-64 qmake which uses arm Qt6 libraries
If you really did a cross compilation the qmake executable should be for the host architecture, not target. How exactly did you do cross compilation?
-
@robgu said in qmake for cross-compiling x86-64 --> armv7:
Therefore, I imagine I need a x86-64 qmake which uses arm Qt6 libraries
If you really did a cross compilation the qmake executable should be for the host architecture, not target. How exactly did you do cross compilation?
@jsulm Thanks for your reply.
Yes, it is for my host architecture (see detail at the bottom of this post).
I have first compiled the sources for the host and then for the target device, providing path to host executables and the toolchain file. The configuration command was as follows:$HOME/Qt654Src/Src/configure -release -opengl es2 -nomake examples -nomake tests -skip qtwebengine -skip qtwebview -skip qtgrpc -qt-host-path $HOME/qt6/bin_host -extprefix $HOME/qt6/bin_b6 -prefix /opt/qt6 -device-option CROSS_COMPILE=arm-poky-linux-gnueabi- -- -DCMAKE_TOOLCHAIN_FILE=$HOME/toolchain.cmakewith the toolchain file:
cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(TARGET_SYSROOT /opt/we-wayland-qt5/2.7.4/sysroots/armv7at2hf-neon-poky-linux-gnueabi/) set(CMAKE_SYSROOT ${TARGET_SYSROOT}) set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:${TARGET_SYSROOT}/usr/lib/pkgconfig) set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/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 arm-poky-linux-gnueabi-gcc) set(CMAKE_CXX_COMPILER arm-poky-linux-gnueabi-g++) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong --sysroot=${TARGET_SYSROOT} -I${TARGET_SYSROOT}/usr/src/kernel-headers/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security") set(QT_COMPILER_FLAGS_RELEASE "-O2 -std=gnu++1z -Wall -W -D_REENTRANT -fPIC -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()It produces the qmake/qmake6 but it is not a full executable: host's one is 1.8M in size while the target's one is 271 bytes and it's a bash script:
#!/bin/sh # The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory. script_dir_path=`dirname $0` script_dir_path=`(cd "$script_dir_path"; /bin/pwd)` /home/ubuntu/qt6/bin_host/bin/qmake6 -qtconf "$script_dir_path/target_qt.conf" $*Understand me well, it is fully operational and I can cross-compile my projects for my target device without problems from the command line (or using another script). But I cannot add it to QtCreator, which I really would like to achieve. Thus, my question about a qmake with cross-compilation compatibility. Or maybe the problem is the old version of QtCreator?
-
@jsulm Thanks for your reply.
Yes, it is for my host architecture (see detail at the bottom of this post).
I have first compiled the sources for the host and then for the target device, providing path to host executables and the toolchain file. The configuration command was as follows:$HOME/Qt654Src/Src/configure -release -opengl es2 -nomake examples -nomake tests -skip qtwebengine -skip qtwebview -skip qtgrpc -qt-host-path $HOME/qt6/bin_host -extprefix $HOME/qt6/bin_b6 -prefix /opt/qt6 -device-option CROSS_COMPILE=arm-poky-linux-gnueabi- -- -DCMAKE_TOOLCHAIN_FILE=$HOME/toolchain.cmakewith the toolchain file:
cmake_minimum_required(VERSION 3.18) include_guard(GLOBAL) set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR arm) set(TARGET_SYSROOT /opt/we-wayland-qt5/2.7.4/sysroots/armv7at2hf-neon-poky-linux-gnueabi/) set(CMAKE_SYSROOT ${TARGET_SYSROOT}) set(ENV{PKG_CONFIG_PATH} $PKG_CONFIG_PATH:${TARGET_SYSROOT}/usr/lib/pkgconfig) set(ENV{PKG_CONFIG_LIBDIR} /usr/lib/pkgconfig:/usr/share/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 arm-poky-linux-gnueabi-gcc) set(CMAKE_CXX_COMPILER arm-poky-linux-gnueabi-g++) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong --sysroot=${TARGET_SYSROOT} -I${TARGET_SYSROOT}/usr/src/kernel-headers/include") set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}") set(QT_COMPILER_FLAGS "-march=armv7-a -mthumb -mfpu=neon -mfloat-abi=hard -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security") set(QT_COMPILER_FLAGS_RELEASE "-O2 -std=gnu++1z -Wall -W -D_REENTRANT -fPIC -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()It produces the qmake/qmake6 but it is not a full executable: host's one is 1.8M in size while the target's one is 271 bytes and it's a bash script:
#!/bin/sh # The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory. script_dir_path=`dirname $0` script_dir_path=`(cd "$script_dir_path"; /bin/pwd)` /home/ubuntu/qt6/bin_host/bin/qmake6 -qtconf "$script_dir_path/target_qt.conf" $*Understand me well, it is fully operational and I can cross-compile my projects for my target device without problems from the command line (or using another script). But I cannot add it to QtCreator, which I really would like to achieve. Thus, my question about a qmake with cross-compilation compatibility. Or maybe the problem is the old version of QtCreator?
@robgu said in qmake for cross-compiling x86-64 --> armv7:
/home/ubuntu/qt6/bin_host/bin/qmake6
Did you try to add that file as qmake executable in QtCreator?
-
@robgu said in qmake for cross-compiling x86-64 --> armv7:
/home/ubuntu/qt6/bin_host/bin/qmake6
Did you try to add that file as qmake executable in QtCreator?
@jsulm Yes, I did try that in the "Kits" section. I get the following error:

I just realized that the qmake/qmake6 I was trying to add to QtCreator (the script one) was trying to use the host tool that was not existing on the correct path: as in previous post the script tries to access
/home/ubuntu/qt6/bin_host/bin/qmake6but this correct path is currently
/opt/bin_host/bin/qmake6Once the script files fixed with the correct path I can successfully add the qmake/qmake6 and define my kit.
@jsulm Thanks again for your questions and iterrest.
-
R robgu has marked this topic as solved on