第2章:交叉编译环境搭建
说实话,很多做嵌入式Linux的朋友,第一步就栽在环境搭建上。不是工具链装不上,就是路径配不对,折腾半天连个Hello World都跑不起来。我当年刚入行时也踩过这个坑,花了整整一个下午才发现是环境变量写错了。
这一章,咱们就把交叉编译环境彻底搞定。你跟着我的步骤来,保证一次过。
2.1 什么是交叉编译?为什么需要它?
先搞清楚一个概念。你平时在PC上写代码,编译出来的程序是给x86架构用的。但ARM开发板是ARM架构,指令集完全不同。你不能在x86上直接编译ARM程序——除非用交叉编译。
交叉编译,说白了就是:
在A架构的机器上,编译出能在B架构上运行的程序。
我们现在的场景是:
宿主机(Host):你的PC,x86架构,Ubuntu系统
目标机(Target):ARM开发板,ARM架构,Linux系统
核心要点:交叉编译工具链里包含了针对ARM架构的编译器、链接器、库文件。它知道怎么生成ARM的机器码,而不是x86的。
2.2 安装交叉编译工具链
我们选用的是 gcc-arm-linux-gnueabihf。这个工具链支持硬件浮点运算(hf = hard float),性能更好。如果你的ARM芯片支持硬件浮点(现在基本都支持),就用这个。
安装方式有两种,我推荐第一种:
方式一:apt 直接安装(推荐)
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf
装完之后,验证一下:
arm-linux-gnueabihf-gcc --version
你应该能看到类似这样的输出:
arm-linux-gnueabihf-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
我的建议:用apt安装最省心。版本可能不是最新的,但稳定。我在项目中一直用7.5.0,从来没出过兼容性问题。
方式二:从Linaro官网下载(进阶)
如果你需要特定版本,可以去Linaro官网下载。步骤稍多:
- 下载工具链压缩包(例如
gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz) - 解压到
/opt目录 - 手动配置环境变量
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt
注意:下载链接可能会变。建议直接去Linaro官网找最新稳定版。我曾经因为用了过期的链接,折腾了半天才发现是404。
2.3 配置环境变量
工具链装好了,但系统还不知道它在哪。你需要把它的路径加到 PATH 里。
我个人习惯把配置写在 ~/.bashrc 里,这样每次打开终端都自动生效。
echo 'export PATH=$PATH:/usr/bin/arm-linux-gnueabihf-' >> ~/.bashrc
source ~/.bashrc
如果你用的是方式二(手动解压到 /opt),路径要改成:
echo 'export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin' >> ~/.bashrc
source ~/.bashrc
验证一下:
which arm-linux-gnueabihf-gcc
如果返回了路径,说明配置成功。
小技巧:你可以用 echo $PATH 查看当前所有路径。如果发现工具链路径没在里面,八成是写错了或者没source。
2.4 编写第一个交叉编译程序:Hello World
环境搭好了,来写个程序验证一下。老规矩,Hello World。
步骤1:写源码
mkdir -p ~/arm_hello
cd ~/arm_hello
vim hello.c
写入以下内容:
#include <stdio.h>
int main()
{
printf("Hello, ARM Linux!\n");
printf("This is my first cross-compiled program.\n");
return 0;
}
步骤2:交叉编译
arm-linux-gnueabihf-gcc hello.c -o hello_arm
编译完成后,用 file 命令看看生成的文件:
file hello_arm
你应该看到类似这样的输出:
hello_arm: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped
看到 ARM 两个字了吗?这说明它确实是ARM架构的可执行文件。
验证要点:如果你在x86的PC上直接运行 ./hello_arm,会报错 Exec format error。这是正常的!因为你的CPU不认识ARM指令。这个程序只能拿到ARM开发板上跑。
步骤3:在ARM开发板上运行
把 hello_arm 拷贝到开发板上。方法很多:
- 通过
scp网络传输 - 通过U盘拷贝
- 通过串口传输(慢,不推荐)
假设你的开发板IP是 192.168.1.100,用户名是 root:
scp hello_arm root@192.168.1.100:/root/
然后在开发板上执行:
chmod +x hello_arm
./hello_arm
如果看到:
Hello, ARM Linux!
This is my first cross-compiled program.
恭喜你,交叉编译环境搭建成功!
2.5 常见问题与避坑指南
| 问题 | 原因 | 解决方法 |
|---|---|---|
command not found |
环境变量没配好 | 检查 PATH,重新 source ~/.bashrc |
Exec format error |
在x86上直接运行ARM程序 | 这是正常的,拷贝到开发板上运行 |
cannot execute binary file |
架构不匹配或权限不足 | 检查 file 输出,确认是ARM;加 chmod +x |
| 编译时提示缺少头文件 | 工具链安装不完整 | 重新安装 gcc-arm-linux-gnueabihf |
我曾经踩过的坑:有一次我编译出来的程序在开发板上跑不起来,提示 Segmentation fault。查了半天,发现是工具链版本和开发板上的glibc版本不匹配。解决办法:要么升级开发板的glibc,要么用更老版本的工具链。从那以后,我每次都会先确认开发板的glibc版本,再选工具链。
2.6 本章小结
这一章我们做了三件事:
- 安装了交叉编译工具链
gcc-arm-linux-gnueabihf - 配置了环境变量,让系统能找到它
- 编写并验证了第一个交叉编译的Hello World程序
现在你的开发环境已经就绪。接下来的章节,我们会在这个基础上,一步步深入ARM驱动的世界。