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 交叉编译工具链使用方法

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

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

相关推荐
JiMoKuangXiangQu2 小时前
Linux ftrace:function tracer 实现简析
linux·ftrace·function tracer
JiMoKuangXiangQu2 小时前
Linux 调度延迟案例 (1):ALSA 播放 XRUN
linux·trace-cmd·xrun·调度延迟
序属秋秋秋2 小时前
《Linux系统编程之进程控制》【进程替换】
linux·c语言·c++·操作系统·进程·系统编程·进程替换
阿拉伯柠檬2 小时前
MySQL内置函数(二)
linux·数据库·mysql·面试
jiedaodezhuti2 小时前
网络安全等级保护:合规基石与风险管理核心
linux
嵌入式@秋刀鱼2 小时前
ROS开发学习记录【一】
linux·c++·笔记·学习
Tipriest_2 小时前
Linux(debian)包管理器aptitude介绍
linux·运维·debian·aptitude
码上宝藏2 小时前
从解耦到拓展:Clapper 0.10.0 插件化架构设计与 Lua 脚本集成
linux·开发语言·lua·视频播放器·clapper
WoY20203 小时前
conda修改镜像源遇到的问题:defaults(默认镜像源)清不干净导致创建环境失败
linux·python·conda