注意事项:本博客所有指令千万不要直接复制执行,因为用户名不一样!

若使用WSL2进行构建,在configure阶段需要等待很久,因为WSL2的IO性能很差

前置条件1:目标系统的glibc版本必须与编译机一致

(树莓派系统推荐编译机使用debian12)

版本过高或过低都会导致链接失败

可以使用以下指令查看glibc的版本

不可使用第三方工具链,如arm的,会缺文件,无法编译

ldd --version

前置条件2:在目标系统上安装必要依赖、打包sysroot

安装依赖

你猜猜为什么有那么多依赖?都是我不断试错,编译了好多次才试出来的。。。

sudo apt update
 
sudo apt install build-essential libgl1-mesa-dev libfontconfig1-dev libdbus-1-dev libssl-dev libudev-dev libinput-dev libts-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-x11-dev libxcb-cursor-dev libxcb-util-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev libxcb-render-util0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-sync-dev libxcb-xinput0

# linux桌面支持:
sudo apt install \
    libfontconfig1-dev \
    libfreetype-dev \
    libgtk-3-dev \
    libx11-dev \
    libx11-xcb-dev \
    libxcb-cursor-dev \
    libxcb-glx0-dev \
    libxcb-icccm4-dev \
    libxcb-image0-dev \
    libxcb-keysyms1-dev \
    libxcb-randr0-dev \
    libxcb-render-util0-dev \
    libxcb-shape0-dev \
    libxcb-shm0-dev \
    libxcb-sync-dev \
    libxcb-util-dev \
    libxcb-xfixes0-dev \
    libxcb-xkb-dev \
    libxcb1-dev \
    libxext-dev \
    libxfixes-dev \
    libxi-dev \
    libxkbcommon-dev \
    libxkbcommon-x11-dev \
    libxrender-dev

sudo apt install \
libxcb1 libx11-xcb1 libxrender1 libxi6 libxkbcommon0 libxext6 libxfixes3 libxrandr2 libxinerama1 libxcursor1 libxcomposite1 libxdamage1 libx11-dev \
libxkbcommon-dev libfontconfig1 libfreetype6 libpng-dev libglib2.0-0 libdbus-1-3 libdbus-1-dev \
libxcb1-dev libxcb-util1 libxcb-util-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-image0 libxcb-image0-dev libxcb-keysyms1 libxcb-keysyms1-dev \
libxcb-render0 libxcb-render0-dev libxcb-shape0 libxcb-shape0-dev libxcb-shm0 libxcb-shm0-dev libxcb-sync1 libxcb-sync-dev libxcb-xfixes0 libxcb-xfixes0-dev \
libxcb-xinerama0 libxcb-xinerama0-dev libxcb-xkb1 libxcb-xkb-dev libxcb-randr0 libxcb-randr0-dev libxcb-composite0 libxcb-composite0-dev libxcb-damage0 libxcb-damage0-dev


 sudo apt-get install \ 
    libxcb1-dev libxcb-icccm4-dev libxcb-image0-dev libxcb-keysyms1-dev \
    libxcb-render0-dev libxcb-render-util0-dev libxcb-shape0-dev libxcb-shm0-dev \
    libxcb-sync-dev libxcb-xfixes0-dev libxcb-xkb-dev libxcb-randr0-dev \
    libxcb-cursor-dev libxcb-glx0-dev libxcb-xinput-dev libx11-dev libx11-xcb-dev \
    libxkbcommon-dev libxkbcommon-x11-dev libxrender-dev libxext-dev libsm-dev libice-dev \
    libfreetype6-dev libfontconfig1-dev libharfbuzz-dev libjpeg-dev libpng-dev libmd4c-dev \
    libgl-dev libegl1-mesa-dev libgles2-mesa-dev libvulkan-dev zlib1g-dev libdrm-dev \
    libinput-dev libts-dev libmtdev-dev libatspi2.0-dev libwayland-dev

sudo apt install libxcb* apt-get install libxkbcommon* 
sudo apt-get install libmd4c-dev          

打包sysroot,会有点久

mkdir -p ~/sysroot
 
这个sudo rsync -avz --delete --exclude='/dev/*' --exclude='/proc/*' --exclude='/sys/*' --exclude='/tmp/*' --exclude='/run/*' --exclude='/mnt/*' --exclude='/media/*' --exclude='/home/*' --exclude='/lost+found' / ~/sysroot 

或者这个(这个还没有试过,这个排除了更多目录,加快速度)sudo rsync -avz --delete \
--exclude='/dev/*' \
--exclude='/proc/*' \
--exclude='/sys/*' \
--exclude='/tmp/*' \
--exclude='/run/*' \
--exclude='/mnt/*' \
--exclude='/media/*' \
--exclude='/home/*' \
--exclude='/lost+found' \
--exclude='/var/lib/docker/*' \
--exclude='/var/run/*' \
--exclude='/var/tmp/*' \
--exclude='/var/cache/*' \
--exclude='/var/lock/*' \
--exclude='/swapfile' \
--exclude='/opt/containerd/*' \
--exclude='/opt/1panel/*' \
--exclude='/opt/pigpio/*' \
--exclude='/opt/Scratch 3/*' \
--exclude='/opt/WidevineCdm/*' \
--exclude='/opt/Wolfram/*' \
/ ~/sysroot

 
sudo tar czf sysroot.tar.gz sysroot

打包完成之后,可以用u盘或其他方式拷贝到编译机

前置条件3:在编译机解压sysroot、安装交叉编译工具

推荐解压到根目录

需要使用root权限

单线程解压:sudo tar xzf ~/sysroot.tar.gz -C ~/
推荐使用多线程解压:sudo tar --use-compress-program=pigz -xvf ~/sysroot.tar.gz

安装交叉编译工具链

此处我还安装了ninja,因为编译过程中make一直报错,换ninja就不报错了

sudo apt update
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu ninja-build libglib2.0-0 libglib2.0-dev libxkbcommon0 libxkbcommon-dev libgl1

sudo apt install -y build-essential cmake ninja-build libgl1 libgl-dev libegl1 libegl-dev libx11-6 libx11-dev libxext6 libxext-dev libxrender1 libxrender-dev libxcb1 libxcb1-dev libxkbcommon0 libxkbcommon-dev libfontconfig1 libfontconfig1-dev libfreetype6 libfreetype6-dev libpng16-16 libpng-dev libjpeg62-turbo libjpeg-dev libinput10 libinput-dev libwayland-client0 libwayland-dev libwayland-egl1 libdrm2 libdrm-dev libgbm1 libgbm-dev libssl-dev zlib1g-dev libsqlite3-dev libicu-dev libdbus-1-3 libdbus-1-dev

编译机安装Qt

推荐一个很快的镜像

--mirror https://mirror.nju.edu.cn/qt/

备注:WSL2也可以使用QT安装器安装,直接运行即可!

参考指令:./qt-online-installer-linux-x64-4.10.0.run --mirror https://mirror.nju.edu.cn/qt/

配置编译环境

  • 进入你安装版本的源码目录:如/home/ska/Qt/6.7.3/Src

  • 创建工具链配置文件:toolchain.cmake

在工具链文件中编写配置信息:(最好不要使用~相对路径,偶尔报错)

请记得修改你的用户名!

set(CMAKE_SYSTEM_NAME Linux) #目标机器系统
set(CMAKE_SYSTEM_PROCESSOR aarch64) #目标架构

# 你的sysroot路径
set(CMAKE_SYSROOT /home/用户名/sysroot)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})

set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)

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_FIND_LIBRARY_SUFFIXES ".so;.a")

此处我们将工具链文件复制一份到上一层,作为Src的配置

cp ./toolchain.cmake ..

设置环境变量

用户名、版本号根据你的实际情况修改

export INSTALL_PATH=/usr/local/raspi-qt6 #qt编译安装的位置

export QT_HOME=/home/用户名/Qt/6.7.3/gcc_64 #用户名、版本号根据你的实际情况修改

编译环节:

创建编译参数:

你可以根据你的需求来配置跳过哪些模块(此处我跳过了很多模块,因为这些模块需要配环境,很麻烦)

如果要在目标机器的桌面运行程序,需要去掉-no-opengl,并且在编译机器配置好opengl的环境。

../configure -release -platform linux-aarch64-gnu-g++ -device linux-aarch64-gnu-gcc -qt-host-path $QT_HOME -prefix $INSTALL_PATH -no-opengl -no-openssl -skip qtgrpc -skip qtprotobuf -skip qtwebengine -skip qtopcua -- -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
带opengl es2版本的指令
../configure -release -platform linux-aarch64-gnu-g++ -device linux-aarch64-gnu-gcc -qt-host-path $QT_HOME -prefix $INSTALL_PATH -opengl es2 -no-openssl -skip qtgrpc -skip qtprotobuf -skip qtwebengine -skip qtopcua -- -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
带xcb的
export PKG_CONFIG_LIBDIR=/home/ska/sysroot/usr/lib/aarch64-linux-gnu/pkgconfig
export PKG_CONFIG_SYSROOT_DIR=/home/ska/sysroot

../configure -release -platform linux-aarch64-gnu-g++ -device linux-aarch64-gnu-gcc -qt-host-path $QT_HOME -prefix $INSTALL_PATH -opengl es2 -no-openssl -skip qtgrpc -skip qtprotobuf -skip qtwebengine -skip qtopcua -xcb -- -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake -DQT_FEATURE_system_md4c=OFF -DQT_FEATURE_md4c=OFF -DXKB_COMMON_X11_LIBRARY=/home/ska/sysroot/usr/lib/aarch64-linux-gnu/libxkbcommon-x11.so -DXKB_COMMON_X11_INCLUDE_DIR=/home/ska/sysroot/usr/include/xkbcommon

开始编译:

cmake --build . --parallel

若编译过程中,遇到dbus链接错误:使用魔法指令

sudo mv /home/用户名/sysroot/usr/lib/aarch64-linux-gnu/libdbus-1.a /home/用户名/sysroot/usr/lib/aarch64-linux-gnu/libdbus-1.a.bak

编译完成后需要使用install将编译好的qt安装到系统

sudo cmake --install .

复制相关库到目标机器

请根据实际情况修改用户名和ip、以及复制到哪个文件夹

scp -r /usr/local/raspi-qt6/* 目标机器用户名@ip地址:/home/用户名/qt6

在目标机器上配置环境变量

根据你用的bash来:vim ~/.bashrc

在最末尾加上:

请记得修改用户名、路径!

export LD_LIBRARY_PATH=/home/用户名/qt6/lib:$LD_LIBRARY_PATH
export QT_PLUGIN_PATH=/home/用户名/qt6/plugins
export QML2_IMPORT_PATH=/home/用户名/qt6/qml
export PATH=/home/用户名/qt6/bin:$PATH

如果你根据步骤来到这里,那么你已经配好了!恭喜!

配置Qt Creator开发环境(后话:不推荐用qt creator!跳到后面使用vscode好):

配置QT版本

填写你编译的路径

配置编译器

连接目标机器

在左侧点击设备

配置构建套件

CMake文件工具链配置:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)

set(CMAKE_SYSROOT /home/ska/sysroot)
set(CMAKE_FIND_ROOT_PATH /home/ska/sysroot /usr/local/raspi-qt6)

set(CMAKE_C_COMPILER /usr/bin/aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/aarch64-linux-gnu-g++)
set(CMAKE_AR /usr/bin/aarch64-linux-gnu-ar)
set(CMAKE_RANLIB /usr/bin/aarch64-linux-gnu-ranlib)
set(CMAKE_OBJDUMP /usr/bin/aarch64-linux-gnu-objdump)

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_PREFIX_PATH "/usr/local/raspi-qt6")


set(CMAKE_FIND_LIBRARY_SUFFIXES ".so;.a")

补充:删除sysroot里的ninja

因为qt creator路径老是会优先去使用sysroot里的ninja,不知道为什么

sudo mv /home/ska/sysroot/usr/bin/ninja /home/ska/sysroot/usr/bin/ninja_bkup

从QT Creator中一键发布程序到目标机器:

建议做完上面那张图片的步骤后,先点一次运行。让文件发布到目标机器,再进行下面的配置。

使用Vscode交叉编译ElaWidget

新建一个工具链配置文件CMakePresets.json

{
    "version": 8,
    "configurePresets": [
        {
            "name": "cross",
            "displayName": "GCC 12.2.0 aarch64-linux-gnu",
            "description": "正在使用编译器: C = /usr/bin/aarch64-linux-gnu-gcc, CXX = /usr/bin/aarch64-linux-gnu-g++",
            "binaryDir": "${sourceDir}/out/build/${presetName}",
            "cacheVariables": {
                "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
                "CMAKE_SYSTEM_NAME": "Linux",
                "CMAKE_SYSTEM_PROCESSOR": "aarch64",
                "CMAKE_SYSROOT": "/home/ska/sysroot",
                "CMAKE_FIND_ROOT_PATH": "/home/ska/sysroot;/usr/local/raspi-qt6",
                "CMAKE_C_COMPILER": "/usr/bin/aarch64-linux-gnu-gcc",
                "CMAKE_CXX_COMPILER": "/usr/bin/aarch64-linux-gnu-g++",
                "CMAKE_FIND_ROOT_PATH_MODE_PROGRAM": "NEVER",
                "CMAKE_FIND_ROOT_PATH_MODE_LIBRARY": "ONLY",
                "CMAKE_FIND_ROOT_PATH_MODE_INCLUDE": "ONLY",
                "CMAKE_FIND_ROOT_PATH_MODE_PACKAGE": "ONLY",
                "CMAKE_FIND_LIBRARY_SUFFIXES": ".so;.a",
                "CMAKE_BUILD_TYPE": "Debug"
            }
        }
    ]
}

CMakeLists.txt修改交叉编译环境的QT路径

SET(QT_SDK_DIR /usr/local/raspi-qt6 CACHE PATH "QT SDK DIR" FORCE)

如果该博客帮到了你,不妨请作者喝杯奶茶~