Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cross-compilation from Windows to aarch64



  • Hello everyone,

    Let me introduce my setup. I have two computers with Qt installed, one on linux (archlinux) and one on Windows 10.
    I'm coding alternately on both of them, and use Qt, and I am very happy because it works great.

    I'm currently trying to develop a new program for a aarch64 architecture (Raspberry Pi 3 B2 - ArchlinuxARM - aarch64).
    I could send the sources to my target and let it compile for me but that would be too simple. I'd like to enhance my programming setup (and knowledge) doing the following things :

    • Cross-compile Qt 5.14.2 for remote deployment from my linux-g++-64 host platform to my linux-aarch64-gnu-g++ target platform
    • Cross-compile Qt 5.14.2 for remote deployment from my win32-g++ host platform to my linux-aarch64-gnu-g++ target platform
      • no luck here, and I need some help.

    I installed the gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu toolchain.

    I am using MinGW 7.3.0 64-bit as host compiler, which I installed with Qt in {Qt_Install_Dir}\Tools\mingw730_64\
    I copied mingw32-make.exe to make.exe because Qt would give me an error if no "make" was found in PATH.

    Perl (Strawberry Perl) and Git (git-scm) are installed and in PATH.
    Both compiler bin directories are in PATH.

    My PATH during compilation is :

    D:\Documents\Programmation\Compilation\qt5\qtrepotools\bin;
    D:\Documents\Programmation\Compilation\qt5\gnuwin32\bin;
    D:\Documents\Programmation\Compilation\qt5\qtbase\bin;
    D:\Documents\Programmation\Compilation\gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu\bin;
    D:\Programmes\Qt\Tools\mingw730_64\bin;
    D:\Programmes\Git\cmd;
    D:\Programmes\Perl\perl\bin;
    D:\Programmes\Git\usr\bin;
    C:\Windows\System32;
    C:\Windows;
    

    I thought I should use linux-aarch64-gnu-g++ as xplatform because it is what I used during my linux computer successful cross-compilation.
    So I modified {Path_to_qt5}\qtbase\mkspecs\linux-aarch64-gnu-g++\qmake.conf with the following content so that it would use my toolchain (given with the CROSS_COMPILE configure variable) instead of the default linux-aarch64-gnu- :

    #
    # qmake configuration for building with $${CROSS_COMPILE}g++
    #
    
    MAKEFILE_GENERATOR      = UNIX
    CONFIG                 += incremental
    QMAKE_INCREMENTAL_STYLE = sublib
    
    include(../common/linux.conf)
    include(../common/gcc-base-unix.conf)
    include(../common/g++-unix.conf)
    
    # modifications to g++.conf
    QMAKE_CC                = $${CROSS_COMPILE}gcc
    QMAKE_CXX               = $${CROSS_COMPILE}g++
    QMAKE_LINK              = $${CROSS_COMPILE}g++
    QMAKE_LINK_SHLIB        = $${CROSS_COMPILE}g++
    
    # modifications to linux.conf
    QMAKE_AR                = $${CROSS_COMPILE}ar cqs
    QMAKE_OBJCOPY           = $${CROSS_COMPILE}objcopy
    QMAKE_NM                = $${CROSS_COMPILE}nm -P
    QMAKE_STRIP             = $${CROSS_COMPILE}strip
    load(qt_config)
    
    

    My compile batch script is the following :

    @echo off
    
    set version=5.14.2
    set qtName=qt%version:~0,1%
    set target=linux-aarch64-gnu-g++
    set filepath=%~dp0
    
    set toolchainName=gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu
    set gccName=aarch64-none-linux-gnu
    
    set buildDir=%filepath%build
    set qtDir=%filepath%%qtName%
    set toolchainDir=%filepath%%toolchainName%
    
    set PATH=C:\Windows;
    set PATH=C:\Windows\System32;%PATH%
    set PATH=D:\Programmes\Git\usr\bin;%PATH%
    set PATH=D:\Programmes\Perl\perl\bin;%PATH%
    set PATH=D:\Programmes\Git\cmd;%PATH%
    set PATH=D:\Programmes\Qt\Tools\mingw730_64\bin;%PATH%
    set PATH=%toolchainDir%\bin;%PATH%
    set PATH=%qtDir%\qtbase\bin;%PATH%
    set PATH=%qtDir%\gnuwin32\bin;%PATH%
    set PATH=%qtDir%\qtrepotools\bin;%PATH%
    
    set crosscompile=%gccName%-
    set sysroot=%toolchainDir:\=/%/%gccName%/libc
    
    set skip=0
    set force=0
    
    for %%i in (%*) do (
    	if "%%i"=="f" (
    		echo Forcing reset
    		set force=1
    	) else (
    		if "%%i"=="s" (
    			echo Skipping
    			set skip=1
    		)
    	)
    )
    
    if "%skip%"=="0" (
    	if "%force%"=="1" (
    		rd /S /Q %qtDir%
    		git clone git://code.qt.io/qt/%qtName%.git
    		cd %qtDir%
    		git checkout %version%
    		perl .\init-repository --module-subset=essential,-qtdoc
    	) else (
    		cd %qtDir%
    		git submodule foreach --recursive "git clean -dfx" && git clean -dfx
    		cd qtbase
    		git reset --hard
    	)
    	
    	copy "%filepath%\qmake.conf" "%qtDir%\qtbase\mkspecs\%target%\"
    )
    
    cd %filepath%
    
    rd  /S /Q %buildDir%
    mkdir %buildDir%
    cd %buildDir%
    
    echo %PATH%
    
    "%qtDir%\configure.bat" -v -release -opensource -platform win32-g++ -xplatform %target% -sysroot %sysroot% -device-option CROSS_COMPILE=%crosscompile% -qt-zlib -nomake examples -no-compile-examples -nomake tests -confirm-license
    
    mingw32-make
    

    My configure command is the following :

    Command line: -v -release -opensource -platform win32-g++ -xplatform linux-aarch64-gnu-g++ -sysroot D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -device-option "CROSS_COMPILE=aarch64-none-linux-gnu-" -qt-zlib -nomake examples -no-compile-examples -nomake tests -confirm-license
    

    The compilation is OK until :

    ##### COMPILING OTHER CLASSES #####
    g++ -c -o registry.o -DUNICODE -DMINGW_HAS_SECURE_API=1 -std=c++11 -ffunction-sections -g  -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/library -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/unix -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/win32 -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/mac -I../include -I../include/QtCore -I../include/QtCore/5.14.2 -I../include/QtCore/5.14.2/QtCore -I../src/corelib/global -ID:/Documents/Programmation/Compilation/qt5/qtbase/mkspecs/win32-g++ -DQT_VERSION_STR=\"5.14.2\" -DQT_VERSION_MAJOR=5  -DQT_VERSION_MINOR=14  -DQT_VERSION_PATCH=2  -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DQT_NO_FOREACH D:/Documents/Programmation/Compilation/qt5/qtbase/qmake/library/registry.cpp
    g++ -c -o qlibraryinfo.o -DUNICODE -DMINGW_HAS_SECURE_API=1 -std=c++11 -ffunction-sections -g  -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/library -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/unix -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/win32 -ID:/Documents/Programmation/Compilation/qt5/qtbase/qmake/generators/mac -I../include -I../include/QtCore -I../include/QtCore/5.14.2 -I../include/QtCore/5.14.2/QtCore -I../src/corelib/global -ID:/Documents/Programmation/Compilation/qt5/qtbase/mkspecs/win32-g++ -DQT_VERSION_STR=\"5.14.2\" -DQT_VERSION_MAJOR=5  -DQT_VERSION_MINOR=14  -DQT_VERSION_PATCH=2  -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL -DQT_NO_FOREACH -DQT_BUILD_QMAKE_BOOTSTRAP D:/Documents/Programmation/Compilation/qt5/qtbase/src/corelib/global/qlibraryinfo.cpp
    g++ -o "../bin/qmake.exe" main.o meta.o option.o project.o property.o ioutils.o proitems.o qmakebuiltins.o qmakeevaluator.o qmakeglobals.o qmakeparser.o qmakevfs.o pbuilder_pbx.o makefile.o makefiledeps.o metamakefile.o projectgenerator.o unixmake2.o unixmake.o mingw_make.o msbuild_objectmodel.o msvc_nmake.o msvc_objectmodel.o msvc_vcproj.o msvc_vcxproj.o winmakefile.o xmloutput.o qutfcodec.o qendian.o qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o qrandom.o qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o qdir.o qdiriterator.o qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o qmetatype.o qsystemerror.o qvariant.o quuid.o qarraydata.o qbitarray.o qbytearray.o qbytearraylist.o qbytearraymatcher.o qcalendar.o qgregoriancalendar.o qromancalendar.o qcryptographichash.o qdatetime.o qhash.o qlist.o qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o qstringbuilder.o qstring.o qstringlist.o qversionnumber.o qvsnprintf.o qxmlstream.o qxmlutils.o qfilesystemengine_win.o qfilesystemiterator_win.o qfsfileengine_win.o qlocale_win.o qsettings_win.o qoperatingsystemversion_win.o qsystemlibrary.o registry.o  qlibraryinfo.o -static -s -lole32 -luuid -ladvapi32 -lkernel32 -lnetapi32 -Wl,--gc-sections
    Info: creating super cache file D:\Documents\Programmation\Compilation\build\.qmake.super
    Info: creating cache file D:\Documents\Programmation\Compilation\build\.qmake.cache
    Command line: -v -release -opensource -platform win32-g++ -xplatform linux-aarch64-gnu-g++ -sysroot D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -device-option "CROSS_COMPILE=aarch64-none-linux-gnu-" -qt-zlib -nomake examples -no-compile-examples -nomake tests -confirm-license
    Info: creating stash file D:\Documents\Programmation\Compilation\build\.qmake.stash
    
    This is the Qt Open Source Edition.
    
    You have already accepted the terms of the Open Source license.
    
    Running configuration tests...
    Checking for machine tuple...
    + aarch64-none-linux-gnu-g++ -dumpmachine
    > aarch64-none-linux-gnu
    test config.qtbase.tests.machineTuple succeeded
    Checking for valid makespec...
    + cd D:\Documents\Programmation\Compilation\build\config.tests\verifyspec && D:\Documents\Programmation\Compilation\build\qtbase\bin\qmake.exe "CONFIG -= qt debug_and_release app_bundle lib_bundle" "CONFIG += shared warn_off console single_arch" "QMAKE_CFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" "QMAKE_CXXFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" "QMAKE_LFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" -early "CONFIG += cross_compile" D:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/verifyspec
    + cd D:\Documents\Programmation\Compilation\build\config.tests\verifyspec && set MAKEFLAGS=& mingw32-make
    > g++ -c --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -O2 -w -fPIC  -ID:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/verifyspec -I. -ID:/Documents/Programmation/Compilation/qt5/qtbase/mkspecs/linux-aarch64-gnu-g++ -o verifyspec.obj D:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/verifyspec/verifyspec.cpp
    > g++ --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -Wl,-O1 -o verifyspec verifyspec.obj
    test config.qtbase.tests.verifyspec succeeded
    Checking for target architecture...
    + cd D:\Documents\Programmation\Compilation\build\config.tests\arch && D:\Documents\Programmation\Compilation\build\qtbase\bin\qmake.exe "CONFIG -= qt debug_and_release app_bundle lib_bundle" "CONFIG += shared warn_off console single_arch" "QMAKE_CFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" "QMAKE_CXXFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" "QMAKE_LFLAGS += --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc" -early "CONFIG += cross_compile" D:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/arch
    + cd D:\Documents\Programmation\Compilation\build\config.tests\arch && set MAKEFLAGS=& mingw32-make
    > g++ -c --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -O2 -w -fPIC  -ID:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/arch -I. -ID:/Documents/Programmation/Compilation/qt5/qtbase/mkspecs/linux-aarch64-gnu-g++ -o arch.obj D:/Documents/Programmation/Compilation/qt5/qtbase/config.tests/arch/arch.cpp
    > g++ --sysroot=D:/Documents/Programmation/Compilation/gcc-arm-9.2-2019.12-mingw-w64-i686-aarch64-none-linux-gnu/aarch64-none-linux-gnu/libc -Wl,-O1 -o arch arch.obj
    Project ERROR: target architecture detection binary not found.
    

    I found no useful information for this error and therefore I think I did somethig wrong.
    Do you have any clue why this error pops up ?

    Thanks a lot for reading,
    Alexis T.



  • @B3lette said in Cross-compilation from Windows to aarch64:

    A couple of side questions please:

    I successfully cross-compiled a simple program and remote-deployed it using QtCreator (I'm super proud btw).

    1. what platform plugin (i.e. EGLFS, LinuxFB, xcb, etc.) do you use to run the app in the target? In particular I'm curious if you're able to run it with EGLFS

    aarch64 architecture (Raspberry Pi 3 B2 - ArchlinuxARM - aarch64)

    1. what ArchlinuxARM OS image did you use?


  • Hello,

    $ uname -a
    Linux rpi3 5.6.5-1-ARCH #1 SMP Mon Apr 20 18:49:23 MDT 2020 aarch64 GNU/Linux
    


  • @B3lette said in Cross-compilation from Windows to aarch64:

    Thanks for the reply.

    The qt5-base is installed on my Pi using the aarch64 qt5-base package

    So next question could be why are you cross-compiling Qt if you already installed a pre-built version of Qt for your device?
    Please, I'm not questioning your approach, just trying to understand your scenario.

    , I think it is using xcb ?

    In that case you should be running X server, are you?

    what if you run your Qt app in RPi device like this:
    ./yourQtApp -platform eglfs



  • So next question could be why are you cross-compiling Qt if you already installed a pre-built version of Qt for your device?
    Please, I'm not questioning your approach, just trying to understand your scenario.

    No problem :)
    Really I'm just beggining to learn about cross compilation. So maybe I'm not doing things the way I should.
    What I want is to have a Qt-5.14.2-aarch64 version of Qt on both of my hosts computers, used in QtCreator to one-click-remote-deploy my program to my Raspberry Pi.
    Are you saying that I could just copy pre-built Qt files from my Pi to my hosts' toolchain's folders and it would work, since I have a cross-compilation toolchain for the correct target installed ? That would be reaaally handy.
    I actually thought of doing it but it seemed far too easy, so I didn't even try.
    Anyway I was trying to learn new things too, and got my linux crosscompilation to work and just wondered why the "same" process would not work on Windows.

    In that case you should be running X server, are you?

    Huh, I'm using my Pi in command line, so I don't have a X server running. My RPi Qt program will be a server-side console app including a QNetworkAccessManager, some QsslSockets, and some QJsonXX objects (for example).

    what if you run your Qt app in RPi device like this:
    ./yourQtApp -platform eglfs

    Actually I deployed another app that took "-p" as a path argument, so this is just giving me my error message for an invalid path ...
    Are you interested in me running another program to check if it works ?



  • I have solved this issue by explicitly write the compiler toolchain in qmake.conf. It seems that the CROSS_COMPILE variable is not propagated to the config.tests compilation.
    I am now having trouble with zlib install prefix management, but that's another story and I'll open a new thread if need be.
    I could post a working batch script which cross-compiles Qt to aarch64.



  • I am following in your footsteps
    Please post your final script on github or here .
    I will be very grateful


Log in to reply