结论速览
- 开发机是 x86_64,MT7621 是 MIPS 小端,普通 PC GCC 生成的机器码目标机执行不了,所以需要
mipsel-linux-gnu-gcc。 - 交叉工具链不只是
gcc,还包括ld、as、objcopy、strip、头文件、libc、动态链接器和启动文件。 - Kernel 和用户程序不强制用同一套工具链,但必须满足 CPU 架构、字节序、ABI 三者兼容;实际工程里统一工具链最省事。
- Kernel 本身就是底层,不链接 glibc/musl,用交叉编译器主要是为了生成正确的目标机器码。
- 即使都叫 MIPS,位宽、端序、ABI、指令集要求不同也会出现
Exec format error、Illegal instruction、动态链接失败。
1. 为什么需要交叉编译
开发机通常是:
1 | x86_64 PC |
目标机 MT7621 是:
1 | MIPS |
普通 PC GCC 默认生成 x86_64 机器码,MT7621 无法执行。
所以需要交叉编译器:
1 | mipsel-linux-gnu-gcc |
含义大致是:
1 | mipsel |
2. 工具链通常包含什么
用户空间交叉工具链通常包含:
1 | gcc |
因此它不只是一个 gcc。
3. Kernel 和应用是否必须用同一个工具链
严格来说不必须。
但必须满足:
1 | CPU 架构兼容 |
例如:
1 | Kernel → MIPS32 little endian |
实际工程中通常统一工具链最省事。
4. Kernel 不依赖 libc
Kernel 和用户程序的编译模型不同。
用户程序:
1 | App |
Kernel:
1 | Kernel |
本身就是底层,不链接 glibc/musl。
所以 Kernel 使用交叉编译器主要是为了生成正确的目标机器码。
5. ABI 为什么重要
即使都是 MIPS,也可能存在:
1 | 32/64 位区别 |
如果 ABI 不兼容,可能出现:
1 | Exec format error |
因此「CPU 名字一样」不等于程序一定兼容。
6. 最简单的实践原则
第一次搭系统时:
1 | Kernel |
尽量都使用同一套 MT7621 交叉工具链。
这样最容易控制变量。