结论速览

  • 开发机是 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
2
MIPS
Little Endian

普通 PC GCC 默认生成 x86_64 机器码,MT7621 无法执行。

所以需要交叉编译器:

1
mipsel-linux-gnu-gcc

含义大致是:

1
2
3
4
5
6
7
8
9
10
11
mipsel
↓
MIPS Little Endian

linux
↓
目标操作系统 ABI 是 Linux

gnu
↓
GNU 工具链体系

2. 工具链通常包含什么

用户空间交叉工具链通常包含:

1
2
3
4
5
6
7
8
9
gcc
ld
as
objcopy
strip
头文件
libc
动态链接器
启动文件

因此它不只是一个 gcc。

3. Kernel 和应用是否必须用同一个工具链

严格来说不必须。

但必须满足:

1
2
3
CPU 架构兼容
字节序兼容
ABI 兼容

例如:

1
2
3
Kernel     → MIPS32 little endian
BusyBox → MIPS32 little endian
App → MIPS32 little endian

实际工程中通常统一工具链最省事。

4. Kernel 不依赖 libc

Kernel 和用户程序的编译模型不同。

用户程序:

1
2
3
4
5
6
7
App
↓
libc
↓
syscall
↓
Kernel

Kernel:

1
Kernel

本身就是底层,不链接 glibc/musl。

所以 Kernel 使用交叉编译器主要是为了生成正确的目标机器码。

5. ABI 为什么重要

即使都是 MIPS,也可能存在:

1
2
3
4
32/64 位区别
大端/小端区别
不同 ABI
不同 CPU 指令集要求

如果 ABI 不兼容,可能出现:

1
2
3
Exec format error
Illegal instruction
动态链接失败

因此「CPU 名字一样」不等于程序一定兼容。

6. 最简单的实践原则

第一次搭系统时:

1
2
3
Kernel
BusyBox
自己的应用

尽量都使用同一套 MT7621 交叉工具链。

这样最容易控制变量。