1、SDK初探:什么是嵌入式Linux SDK、SDK的典型目录结构、如何获取和安装SDK、搭建交叉编译环境

1.1 到底什么是嵌入式Linux SDK?

说实话,我刚入行那会儿,也被「SDK」这个词搞得云里雾里的。听着挺高大上,其实说白了——嵌入式Linux SDK就是一套让你能在PC上开发、编译、调试嵌入式设备的工具集合。

你想想看,嵌入式设备(比如路由器、机顶盒、智能摄像头)的CPU架构通常是ARM、MIPS或者RISC-V。你的PC是x86架构。直接在PC上编译出来的程序,设备跑不了。怎么办?

SDK就是来解决这个问题的。它包含:

  • 交叉编译工具链(编译器、链接器、调试器)
  • 目标系统的头文件和库
  • 构建脚本和配置文件
  • 一些实用工具(比如烧录工具、调试工具)

核心理解:SDK = 交叉编译工具链 + 目标系统根文件系统 + 构建系统。缺一不可。

我个人习惯把SDK比作「翻译官」。你在PC上写代码,SDK帮你翻译成设备能听懂的语言。没有它,你写的程序就是一堆废纸。

1.2 SDK的典型目录结构

不同芯片厂商的SDK长得不太一样,但骨架基本一致。我拿一个典型的全志/瑞芯微SDK举例:

sdk_root/
├── build/               # 构建脚本和配置文件
│   ├── configs/         # 板级配置(板子型号、内核配置)
│   └── toolchain/       # 工具链构建脚本
├── kernel/              # Linux内核源码
│   ├── arch/            # 架构相关代码(arm64、riscv等)
│   └── drivers/         # 设备驱动
├── u-boot/              # 引导加载程序
├── buildroot/           # 根文件系统构建工具(或Yocto)
├── output/              # 编译输出目录
│   ├── images/          # 最终镜像文件(boot.img、rootfs.img)
│   └── staging/         # 目标系统的头文件和库
├── tools/               # 主机端工具(烧录、调试)
├── external/            # 第三方软件包
└── docs/                # 文档(嗯,通常比较简陋)

这里我特别想强调output/staging这个目录。很多新手会忽略它,但它其实是你交叉编译时最常打交道的地方。里面放着目标系统的usr/include和usr/lib——说白了,就是你在PC上编译程序时,需要链接的那些库和头文件。

我的经验:拿到一个陌生SDK,先看build/configs/目录。里面通常有defconfig文件,记录了板子的硬件配置。我当年接手一个项目,板子死活起不来,最后发现是DDR配置参数写错了。嗯,从那以后我养成了先看配置文件的习惯。

1.3 如何获取和安装SDK

获取SDK的途径,我总结下来就三种:

  1. 芯片厂商官方提供(最常见)—— 比如全志的Tina SDK、瑞芯微的RK SDK。去官网注册开发者账号,下载即可。
  2. 开发板厂商提供—— 比如树莓派、BeagleBone。通常在官网的「Downloads」或「Resources」页面。
  3. 自己从开源社区构建—— 用Buildroot或Yocto自己定制。适合有特殊需求的团队。

安装SDK,我建议按这个步骤来:

# 1. 解压SDK(通常是个tar.gz包)
tar -xzf sdk_xxx.tar.gz -C ~/workspace/

# 2. 安装依赖(不同发行版略有差异)
sudo apt-get install build-essential git libncurses-dev flex bison

# 3. 设置环境变量(我习惯写在~/.bashrc里)
export SDK_PATH=~/workspace/sdk_root
export PATH=$SDK_PATH/tools:$PATH

# 4. 验证安装
arm-linux-gnueabihf-gcc --version

注意:我曾经在一个Ubuntu 22.04系统上装了个老旧的SDK,结果编译报错——因为新系统的glibc版本太高,和老工具链不兼容。解决办法是用Docker创建一个Ubuntu 18.04的环境。所以,SDK的安装环境最好和厂商推荐的保持一致。

1.4 搭建交叉编译环境

交叉编译环境,说白了就是让你的PC能编译出目标设备能运行的程序。核心就三步:

1.4.1 确认工具链前缀

不同架构的工具链前缀不一样:

目标架构 工具链前缀 示例
ARM 32位 arm-linux-gnueabihf- arm-linux-gnueabihf-gcc
ARM 64位 aarch64-linux-gnu- aarch64-linux-gnu-gcc
MIPS mips-linux-gnu- mips-linux-gnu-gcc
RISC-V 64位 riscv64-linux-gnu- riscv64-linux-gnu-gcc

1.4.2 编写一个简单的测试程序

我习惯先写个Hello World验证环境:

// hello.c
#include <stdio.h>

int main() {
    printf("Hello from Embedded Linux!\n");
    return 0;
}
# 交叉编译
arm-linux-gnueabihf-gcc -o hello hello.c

# 查看生成的文件信息
file hello
# 输出:ELF 32-bit LSB executable, ARM, version 1 (SYSV)

看到ARM字样,说明编译成功了。如果显示x86-64,那就是用了本机编译器——嗯,我刚开始也犯过这个错。

1.4.3 配置环境变量(一劳永逸)

每次编译都敲一长串前缀太麻烦。我建议这样:

# 在~/.bashrc中添加
export CROSS_COMPILE=arm-linux-gnueabihf-
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export AR=${CROSS_COMPILE}ar
export LD=${CROSS_COMPILE}ld

# 然后
source ~/.bashrc

# 之后编译就可以直接用$CC了
$CC -o hello hello.c

避坑指南:我曾经在一个项目里,直接用了gcc而不是$CC,结果编译出来的程序在板子上跑不了。查了半天才发现是用了本机编译器。所以,每次编译前,确认一下$CC指向的是交叉编译器。养成习惯,能省很多时间。

1.5 本章知识体系

下面这张图,是我自己总结的SDK核心逻辑。你看一眼,就能把整章内容串起来:

嵌入式Linux SDK核心逻辑 主机PC (x86) 交叉编译工具链 SDK构建脚本 目标系统库/头文件 交叉编译 SDK核心 Kernel源码 U-Boot源码 Buildroot/Yocto 生成镜像 目标设备 ARM/MIPS RISC-V 运行程序 SDK = 交叉编译工具链 + 目标系统根文件系统 + 构建系统 获取SDK 厂商官网 / 开源社区 安装SDK 解压 → 装依赖 → 设环境变量 交叉编译 确认前缀 → 编译 → 验证

这张图把SDK的整个工作流讲清楚了:PC上开发 → SDK编译 → 生成镜像 → 设备运行。你只要记住这个流程,后面学起来就顺了。


好了,这一章就到这里。SDK的安装和交叉编译环境搭建,是后续所有优化的基础。别嫌麻烦,把这一步走稳了,后面才能跑得快。

可可精品资料库