
**摘要:**在嵌入式Linux应用层开发的旅程中,交叉编译是不可或缺的一环。本文以经典的"Hello World"程序为例,详细阐述了如何使用arm-buildroot-linux-gnueabihf-gcc交叉编译工具链,为ARM平台生成可执行文件。我们不仅展示了基本的交叉编译命令,还深入探讨了交叉编译过程中工具链路径的配置、头文件与库文件的默认路径查询及自定义方法。
1. 为什么要学习交叉编译?
在 Linux 应用层开发中,我们经常面临这样一种场景:
- 开发环境:x86 PC(Ubuntu / Debian / WSL 等)
- 运行环境:ARM 嵌入式设备(开发板、网关、工控机等)
注意:由于 处理器架构不同 ,PC 上直接使用 gcc 编译生成的程序无法在 ARM 平台运行 。因此,需要使用交叉编译(Cross Compilation) 技术,在 PC 上生成 ARM 平台可执行文件。
📌 交叉编译的本质:
在一种平台上(x86)编译,生成另一种平台(ARM)可执行程序。
2. 实验环境说明
本文假设你已具备以下基本环境:
-
主机:Linux(Ubuntu / Debian 等)
-
交叉编译工具链:
arm-buildroot-linux-gnueabihf-gcc
-
目标平台:ARM Linux 开发板(支持运行 ELF 可执行文件)
若使用的是 Buildroot、Yocto 或厂商 SDK,工具链名称可能略有不同,但原理完全一致。
3. 第一个 Linux 应用程序:hello.c
我们先编写一个最简单但稍微增强版的 Hello World 程序:
cs
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc >= 2)
printf("Hello, %s!\n", argv[1]);
else
printf("Hello, world!\n");
return 0;
}
该程序支持 两种运行模式:
| 运行方式 | 输出结果 |
|---|---|
./hello |
Hello, world! |
./hello xiaochengstudent |
Hello, xiaochengstudent! |
📌 设计目的:
- 引入
argc / argv参数机制 - 为后续命令行程序开发打基础
- 比纯 Hello World 更贴近真实应用
4. 使用交叉编译工具链编译 hello.c
4.1 使用 ARM 交叉编译器
在 PC 或虚拟机ubuntu上执行:
arm-buildroot-linux-gnueabihf-gcc -o hello hello.c
生成的 hello 文件即为 ARM 平台可执行程序。

4.2 在 ARM 开发板上运行
采用ADB将 hello 上传到开发板(scp / nfs / u 盘)后:
cs
adb push hello ./root
// 该命令将 pc/虚拟机ubuntu中当前目录的hello 上传到 arm开发板中的.root目录
在开发板中输入以下代码:
cs
./hello
输出:
Hello, world!
带参数运行:
./hello Linux
输出:
Hello, Linux!
5. PC 平台与 ARM 平台编译的区别
5.1 PC 平台编译(本机 gcc)
gcc -o hello hello.c
📌 生成结果:
-
仅能在 x86 Linux 上运行
-
拷贝到 ARM 板运行会报错:
cannot execute binary file
5.2 验证可执行文件架构
使用 file 命令查看:
file hello
ARM 程序示例输出:
ELF 32-bit LSB executable, ARM, EABI5
x86 程序示例输出:
ELF 64-bit LSB executable, x86-64
6. 交叉编译工具链的头文件路径
6.1 为什么需要关注头文件路径?
交叉编译时:
stdio.hstdlib.hstring.h
并不是使用 PC 系统的头文件 ,而是使用 交叉工具链自带的头文件。
6.2 查询默认头文件路径
进入交叉编译器安装目录:
cd /opt/arm-buildroot/
执行:
find . -name "stdio.h"
示例输出:
./arm-buildroot-linux-gnueabihf/sysroot/usr/include/stdio.h
📌 说明:
sysroot/usr/include即为默认头文件根目录- 编译器会自动搜索该路径,无需手动指定
6.3 使用自定义头文件目录(-I)
若项目中有自定义头文件:
arm-buildroot-linux-gnueabihf-gcc \
-I /custom/include/path \
-o hello hello.c
📌 -I 的作用:
- 告诉编译器:额外去哪里找头文件
7. 交叉编译中的库文件路径
7.1 查询默认库文件路径
在工具链目录中查找:
find . -name lib
常见结果:
sysroot/lib
sysroot/usr/lib
📌 一般选择:
- 含有
.so或.a文件的目录 usr/lib更常见
7.2 指定自定义库路径(-L)
cs
arm-buildroot-linux-gnueabihf-gcc -L /custom/lib/path -o hello hello.c
7.3 链接指定库(-l)
假设存在动态库:
libabc.so
链接方式:
cs
arm-buildroot-linux-gnueabihf-gcc -labc -o hello hello.c
📌 注意事项:
-labc实际链接的是libabc.so- 库名去掉
lib和.so
8. 交叉编译常见问题解析
8.1 No such file or directory(头文件找不到)
原因:
- 未指定头文件路径
- 使用了 PC 的路径
解决方法:
-I 正确的 include 路径
8.2 undefined reference(链接错误)
原因:
- 缺少库
- 链接顺序错误
解决方法:
-L 库路径 -l库名
8.3 ARM 板运行报错:not found
可能原因:
- 动态库未拷贝到 ARM 板
- 运行环境缺少依赖库
📌 排查方式:
ldd hello
9. 小结
在本文中,我们完成了 Linux 应用层开发的第一步:
✔ 编写第一个 Linux 应用程序
✔ 理解 PC 编译与交叉编译的区别
✔ 掌握 ARM 交叉编译工具链使用方法
✔ 学会配置头文件与库文件路径
✔ 理解常见编译与运行错误的原因