1.概述
linux系统下C++程序开发,主要依赖处理器的架构(x86架构,Arm架构)。为了达到跨平台移植的目的。可以采用俩种方案:
- CMakeLists组织编译工程,目标机器上重新编译;
- 利用交叉编译器在宿主机器上进行交叉编译,然后将可执行文件拷贝到目标机器,直接运行。
2.方案一 ~ 交叉编译
以下以qt程序开发为例
-
下载交叉编译器工具链:详细地址
解压,主要使用bin文件夹下的可执行文件
设置交叉编译工具链环境变量/etc/bash.bashc
# Add Arm toolschain path if [ -d /usr/local/ARM-toolschain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu ]; then PATH=/usr/local/ARM-toolschain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:"${PATH}" fi
-
编译框架(qt)
下载qt源码
配置交叉编译:qtbase/mkspecs/linux-aarch-gnu-g++/qmake.conf
# qmake configuration for building with aarch64-linux-gnu-g++ # MAKEFILE_GENERATOR = UNIX CONFIG += incremental QMAKE_INCREMENTAL_STYLE = sublib QT_QPA_DEFAULT_PLATFORM = linuxfb QMAKE_CFLAGS_RELEASE += -O2 -march=armv8-a -lts QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv8-a -lts include(../common/linux.conf) include(../common/gcc-base-unix.conf) include(../common/g++-unix.conf) #modifications to g++.conf QMAKE_CC = aarch64-linux-gnu-gcc QMAKE_CXX = aarch64-linux-gnu-g++ QMAKE_LINK = aarch64-linux-gnu-g++ QMAKE_LINK_SHLIB = aarch64-linux-gnu-g++ #modifications to linux.conf QMAKE_AR = aarch64-linux-gnu-ar cqs QMAKE_OBJCOPY = aarch64-linux-gnu-objcopy QMAKE_NM = aarch64-linux-gnu-nm -P QMAKE_STRIP = aarch64-linux-gnu-strip load(qt_config)
编译 build.sh:
#!/bin/sh ./configure \ -prefix /usr/bin/qt5.12.10-arm \ -confirm-license \ -opensource \ -release \ -make libs \ -xplatform linux-aarch64-gnu-g++ \ -pch \ -qt-libjpeg \ -qt-libpng \ -qt-zlib \ -no-opengl \ -no-sse2 \ -no-openssl \ -no-cups \ -no-glib \ -no-dbus \ -no-xcb \ -no-separate-debug-info
sudo make -j8
sudo make install
-
配置qtcreator
选择安装文件夹下的qmake,默认为:/urs/local/Qt-**/bin/qmake
-
编译
在Qtcreator中进行编译,切记不要调试和运行,否则报错。如果需要调试,则需要安装交叉链编译的gdb,配置好后便可远程调试,否则只能以打印日志的形式进行运行调试。 -
配置目标机环境(Arm开发板)
由于在宿主机上不能使用ldd方式查询所需动态库,所以需要完整拷贝所有lib
– 拷贝lib库
– 拷贝plugins/imageformats到当前文件夹(qt程序特有的,如果用到其它可能还需要添加)
– 设置环境变量(三种方式:linux常规命令—动态库路径配置):
# vim /etc/ld.so.conf.d/qt.5.12.10.conf
/opt/Qt/lib
# sudo ldconfig
# ldd app
-
交叉编译gdb(7.5)
下载gdb: 交叉编译源码预处理
sudo apt-get install texinfo m4 flex bison libncurses5-dev
sudo apt-get install gdb-multiarch
编译gdb(本地直接调用 /usr/bin/gdb-multiarch)
./configure --target=aarch64-linux-gnu --program-prefix=aarch64-linux- --prefix=/usr/local/arm-gdb --disable-werror
make -j4
sudo make install
添加环境变量(待选,不需要直接加入)
sudo vi /etc/bash.bashrc
# export PATH=$PATH:/usr/local/aarch-gdb/bin
压缩可执行文件体积
strip arm-linux-gdb - o arm-linux-stripped
编译gdbserver(如果编译失败,参考注意事项)
cd ./gdbserver
./configure --target=aarch64-linux-gnu --host=aarch64-linux-gnu
make CC=交叉编译器路径
-
交叉编译gdb(10.1)
10.1需要aarch64的gdbsupport/libgdbsupport.o支持,选择直接交叉编译gdb
./configure --target=aarch64-linux-gnu --host=aarch64-linux-gnu --disable-werror
make -j4
编译完成,无需安装,直接拷贝./gdbserver下文件gdbserver
到目标机器下即可
注:
--build:运行编译工具链的平台,也就是正在执行编译操作的平台。如果未指定此参数,则通过 config.guess 猜测得到。通常都不指定此参数。
--host:可执行程序将运行的平台。如果未指定此函数,则和 --build 相同。如果 --host 和 --build 不同,是交叉编译;否则是普通编译。
--target:可执行程序将处理的平台。如果未指定此函数,则和 --host 相同。一般来说,程序运行在什么平台,处理的就是什么平台,此参数值和 --host 参数相同,不需显式指定所以通常不会关注到此参数。但在制作交叉编译工具 (如 gcc、gdb 等) 这种特殊情况的时候下,此值和 --host 不同,例如编译生成 arm-linux-gcc 程序,它运行在 x86-linux 平台 (--host 参数),但处理的是 arm-linux 平台 (--target 参数)。如果是交叉编译一个普通的应用,如运行于 arm-linux 平台的 tftp 程序,则它的运行平台和处理平台都是 arm-linux 平台。
可能存在的错误
1). 编译gdb出错: `recipe for target 'sub-plugins-make_first' failed`
上次编译残留,重新解压源码编译
`make clean -w`
2). 运行qt源码:`cannot deploy: no device configuration set`
该程序只能编译不能运行,需要一移植目标机器上方能运行,或者配置gdb
3). 编译gdbserver出错:`Relocations in generic ELF (EM: 62)`
查看动态库编译格式:`objdump -a **.lib`
4). __NR_sigreturn not declared
vim linux-arm-low.cc
#ifndef __NR_sigreturn
#include <asm/unistd_32.h>
#endif
5).qtcreator sftp upload文件失败
vim /etc/ssh/sshd_config
PermitRootLogin yes
sudo service sshd restart
查看 ps -au|grep sshd
6).如果交叉编译过程出现源码错误,请核查交叉编译环境是否配置成功,使用demo测试,然后重新解压缩源码,configure,make
7).安装Qtcreator可能无法运行,需要安装`apt-get install libxcb-xinerama0`
8).编译时出现缺少头文件,可以先查看头文件路径(“aarch64-linux-gnu-g++ -v”),然后查找所需头文件位置("find / -name "libio.h""),拷贝该文件到头文件路径下即可("cp -r source_folder destination_folder")
2.方案二 ~ CMakeLists源码编译
可能存在的错误
You have changed variables that require your cache to be deleted
子项中包含调用默认编译器的程序