Linux 应用层开发入门(一)| ARM平台交叉编译入门:打造你的第一个Linux应用

**摘要‌:**在嵌入式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.h
  • stdlib.h
  • string.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 交叉编译工具链使用方法

✔ 学会配置头文件与库文件路径

✔ 理解常见编译与运行错误的原因

相关推荐
雯宝3 小时前
mnt_init 函数
linux
律宏阔9 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔9 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴9 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千9 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei379 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei379 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei379 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW9 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
GeW9 小时前
工业场景中的Linux与数据库选型:高端化转型的技术底座
linux