交叉编译的概念
交叉编译是解决资源受限设备开发、跨平台兼容性和开发效率问题的关键技术。
交叉编译是指在一种计算机系统(通常称为 宿主机(Host))上编译生成另一种计算机系统(称为 目标机(Target))可执行的代码或程序的过程。其核心特点是编译环境与运行环境不一致,常用于开发需要在不同架构、操作系统或硬件平台上运行的软件
交叉编译工具链
交叉编译工具链是跨平台开发的核心基础设施
32位工具链和64位工具链核心区别
对比维度 | 32 位工具链 | 64 位工具链 |
---|---|---|
寻址能力 | 支持最大 4GB 内存寻址(2^32 字节) | 支持 TB 级内存寻址(2^64 字节) |
寄存器宽度 | 32 位通用寄存器(如 EAX、EBX) | 64 位通用寄存器(如 RAX、RBX) |
数据模型 | LP32/LP64(Linux/Unix) | ILP64(整数、长整型、指针均为 64 位) |
指针大小 | 32 位(4 字节) | 64 位(8 字节) |
性能特点 | 内存占用少,适合资源受限设备 | 处理大数据和复杂计算时性能更优 |
典型工具链前缀 | arm-linux-gnueabihf- (32 位 ARM) |
aarch64-linux-gnu- (64 位 ARM) |
i686-linux-gnu- (32 位 x86) |
x86_64-linux-gnu- (64 位 x86) |
32位工具链的获取:
sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf
64位工具链的获取:
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
这里可以两个都下载方便以后使用
查看工具链位置
which arm-linux-gnueabihf-gcc//32位
which aarch64-linux-gnu-gcc//64位
为了避免每次使用工具链都需输入完整路径,所以我们需要配置环境变量
获得当前环境变量
echo $PATH
临时有效
export PATH=$PATH:/path/to/toolchain/bin # 将工具链的bin目录添加到PATH中
永久有效
修改工作目录下的.bashrc 隐藏文件,配置命令终端
vi ~/.bashrc
在末尾添加以下代码可以使用32bit或64bit指令来自由切换32位或者64位编译工具链
#!/bin/bash
# 树莓派内核编译环境配置(32位/64位切换)
# ----------------------
# 工具链路径(根据实际路径修改)
# ----------------------
export TOOLCHAIN_64=~/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu
export TOOLCHAIN_32=~/toolchain/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf
# ----------------------
# 环境变量初始化
# ----------------------
# 保存原始PATH(不含工具链)
if [ -z "$ORIG_PATH" ]; then
ORIG_PATH=$(echo "$PATH" | tr ':' '\n' | grep -vF "$TOOLCHAIN_64/bin" | grep -vF "$TOOLCHAIN_32/bin" | tr '\n' ':' | sed 's/:$//')
fi
# ----------------------
# 环境管理函数
# ----------------------
# 重置环境(清除工具链路径和变量)
function reset_env() {
export PATH="$ORIG_PATH"
unset ARCH KERNEL CROSS_COMPILE
echo -e "\e[32m环境已重置\e[0m"
}
# 切换到64位环境
function arm64env() {
reset_env # 清除旧环境
export ARCH=arm64 # 设置架构为64位ARM
export KERNEL=kernel8 # 设置内核镜像名称
export CROSS_COMPILE=aarch64-linux-gnu- # 设置交叉编译器前缀
export PATH="$TOOLCHAIN_64/bin:$PATH" # 添加64位工具链到PATH最前
echo -e "\e[34m当前为64位编译环境\e[0m"
envcheck # 验证环境配置
}
# 切换到32位环境
function arm32env() {
reset_env # 清除旧环境
export ARCH=arm # 设置架构为32位ARM
export KERNEL=kernel7 # 设置内核镜像名称
export CROSS_COMPILE=arm-linux-gnueabihf- # 设置交叉编译器前缀
export PATH="$TOOLCHAIN_32/bin:$PATH" # 添加32位工具链到PATH最前
echo -e "\e[34m当前为32位编译环境\e[0m"
envcheck # 验证环境配置
}
# ----------------------
# 环境检查函数
# ----------------------
function envcheck() {
echo -e "\n\e[32m环境参数:\e[0m"
echo "ARCH=$ARCH"
echo "KERNEL=$KERNEL"
echo "CROSS_COMPILE=$CROSS_COMPILE"
echo -e "\n\e[32m工具链路径:\e[0m"
echo "$PATH" | tr ':' '\n' | grep -E "$TOOLCHAIN_64|$TOOLCHAIN_32" || echo "无"
echo -e "\n\e[32m编译器版本:\e[0m"
${CROSS_COMPILE}gcc --version 2>/dev/null || echo "未找到编译器"
echo -e ""
}
# ----------------------
# 快捷命令别名
# ----------------------
alias 64bit='arm64env' # 切换64位环境
alias 32bit='arm32env' # 切换32位环境
alias envchk='envcheck' # 检查环境
alias rst='reset_env' # 重置环境
# ----------------------
# 终端启动时默认加载32位环境(可选)
# ----------------------
if [[ $- == *i* && -z "$ARCH" ]]; then
arm32env
fi
使用交叉编译工具
arm-linux-gnueabihf-gcc xxx.c -o xxx
把编译生成的可执行文件下载到树莓派
scp xxx pi@192.168.1.9:/home/pi
//指令 文件名 开发板用户名@开发板地址:开发板的绝对路径
使用交叉编译编译ftp服务端客户端
我们以前在/FTP目录下写过FTP服务器的服务端和客户端的代码这里可以交叉编译service.c命名为service_Pi然后传输给树莓派
然后运行看看效果
带WiringPi库的交叉编译
1. 获取 WiringPi 库:
git clone https://github.com/WiringPi/WiringPi.git
cd WiringPi
2.交叉编译 WiringPi 库
(1)修改编译配置:
进入 WiringPi 源码目录后,需修改相关编译配置文件(通常是Makefile或build脚本 ),将其中的编译器指定为交叉编译器。比如,若使用arm-linux-gnueabihf-gcc,则将CC变量改为arm-linux-gnueabihf-gcc,CXX变量改为arm-linux-gnueabihf-g++ 。
(2)编译库文件:
修改完配置后,执行编译命令。一般执行./build 脚本(如果有),或者使用make命令进行编译。编译成功后,会生成适用于目标 ARM 架构的 WiringPi 库文件(如libwiringPi.a或libwiringPi.so )
3.交叉编译应用程序
从树莓派传过来一个使用 WiringPi 库的 C 语言源文件(如test.c
)
arm-linux-gnueabihf-gcc -o test test.c -I/path/to/WiringPi/wiringPi -L/path/to/WiringPi -lwiringPi
#-I/path/to/WiringPi/wiringPi:指定 WiringPi 头文件的路径,确保编译器能找到wiringPi.h等头文件
#-L/path/to/WiringPi:指定编译生成的 WiringPi 库文件所在路径
#-lwiringPi:指定链接 WiringPi 库
也可以直接把树莓派的WiringPi库拿上来用
如果想去掉库后面的版本号的话可以通过软连接和硬链接的方式
硬链接:是在同一文件系统内,创建指向同一文件数据块的多个引用,相当于文件的多个 “别名” 这些引用共享相同的 inode(索引节点),只要还有一个硬连接存在,文件数据就不会丢失 ,不过,硬连接不能跨文件系统创建,也不能用于目录
软链接:也叫符号链接,是一个特殊文件,其内容为指向另一个文件或目录的路径,类似 Windows 系统中的快捷方式 。软连接有自己独立的 inode ,可跨文件系统创建,也能指向目录 。若目标文件被删除或移动,软连接会变成 “断链” 而失效 。
生成软连接
ln -s libwiringPi.so.2.52 libwiringPi.so
生成硬链接
ln libwiringPi.so.2.52 libwiringPi.so
此时要用传过来的WiringPi库的话可以在 -lwiringPi 前加一个-L.表示在当前目录搜索库文件
arm-linux-gnueabihf-gcc -o test test.c -I/path/to/WiringPi/wiringPi -L/path/to/WiringPi -L. -lwiringPi