Linux 上配环境反而最简单:没有「找 DLL」这回事, 包管理器装完、pkg-config 一给参数就能编。
前两节讲了 Windows 和 Qt,这一节补上 Linux。 三平台的差别其实只有三处:依赖从哪来、编时怎么找、跑时怎么找。 看清这三处,跨平台就不再神秘。 沙箱是 Windows,所以这一节的命令没法真跑,能给的是清单加平台判断代码。
一、装什么
SDL2 一个包,FFmpeg 五个包。
| 包 | 给什么 |
|---|---|
libsdl2-dev |
SDL2 头文件与库 |
libavformat-dev |
容器与协议 |
libavcodec-dev |
编解码器 |
libavutil-dev |
工具函数与时间基 |
libswscale-dev |
像素格式转换 |
libswresample-dev |
音频重采样 |
注意都是 -dev 包:不带 -dev 的那个只能跑不能编,报错是「找不到 avformat.h」。
这个错很常见,因为运行时包通常已经预装了——于是你以为是「没装 FFmpeg」,其实是「没装头文件」。
二、编译不用手写一堆 -l
pkg-config 就是「库的说明书查询工具」。
| 命令 | 给什么 | 用在哪 |
|---|---|---|
--cflags |
-I… 头文件路径 |
编译 |
--libs |
-l… 链接参数 |
链接 |
--modversion |
版本号 | 验证装没装对 |
一句 pkg-config --modversion sdl2 就能确认装没装对,比翻 /usr/lib 快得多。
而且它给的是「这台机器上正确的路径」,不用管是 x86 还是 arm。
三、三个平台的差别就三行
同一份源码,三个平台只差这三件事:
| Windows | Linux | |
|---|---|---|
| 依赖从哪来 | 手动下 zip 放固定目录 | apt 装到系统路径 |
| 编时怎么找 | 项目属性里填路径 | pkg-config 自动给 |
| 跑时怎么找 | DLL 放 exe 旁边 | so 在 /usr/lib,不用管 |
第二、三行是新手最容易翻车的地方:Windows 上「编过了」和「跑得起来」是两件事, Linux 上一般是一件。 这也解释了为什么很多开源项目在 Linux 上装完就能跑,到了 Windows 要配半天。
四、平台判断该写在哪
要写平台相关代码时,别用「编译器宏」,用 SDL 自己的函数。
| 写法 | 好处 | 坏处 |
|---|---|---|
SDL_GetPlatform() |
SDL 已经判断过了 | 要在 SDL 初始化后调 |
#ifdef _WIN32 |
编的时候就定了 | 一堆宏,容易漏 |
sys.platform(Python) |
简单 | 只到操作系统级 |
第一行最省事:D31 实测返回 Windows,Linux 上返回 Linux,macOS 上返回 macOS。
注意它是运行时的——同一个二进制不会跨平台,但同一个源码要能编出三个二进制,
这时候第一行和第三行都行。
五、动手 Demo:查平台、列依赖、对比三平台
先让 SDL 自己报平台名,再把 Linux 上要装的东西列清,最后把三平台的差别摆成一张表。 沙箱是 Windows,所以这一节只验「平台判断」,装包的部分只能照做。
import sdl2
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
print(sdl2.SDL_GetPlatform()) # b"Windows"
# Linux 上要装(照抄即可)
# sudo apt install libsdl2-dev
# sudo apt install libavformat-dev libavcodec-dev libavutil-dev
# sudo apt install libswscale-dev libswresample-dev
# 编译:交给 pkg-config
# gcc main.c -o main $(pkg-config --cflags --libs sdl2 \
# libavformat libavcodec)
实跑输出:
--------------------------------------------------------------------
Linux 上配 SDL2,一条 apt 加一个 pkg-config
--------------------------------------------------------------------
**Linux 反而最简单:没有「找 DLL」这回事,包管理器装完就能编。**
本机是 Windows,`SDL_GetPlatform()` 会告诉我们:
当前平台:**Windows**
**这个函数在跨平台代码里很有用**:同一个二进制不可能跨平台,但同一份源码可以,靠它分支。
**Linux 上要装的东西:**
sudo apt install libsdl2-dev
sudo apt install libavformat-dev libavcodec-dev libavutil-dev
sudo apt install libswscale-dev libswresample-dev
**编译命令不用手写一堆 `-l`,交给 pkg-config:**
gcc main.c -o main $(pkg-config --cflags --libs sdl2 libavformat libavcodec)
**`--cflags` 给头文件路径,`--libs` 给链接参数**,一起给就是完整的编译行。
验证装没装对,只要一句 `pkg-config --modversion sdl2`。
**三个平台真正的差别就这三处:**
Windows Linux
--------------------------------------------------------------------
依赖从哪来 手动下 zip,放固定目录 apt 装到系统路径
编时怎么找 项目属性里填路径 pkg-config 自动给
跑时怎么找 DLL 放 exe 旁边 so 在 /usr/lib,不用管
**第二行和第三行是新手最容易翻车的**:Windows 上「编过了」和「跑得起来」是两件事,
Linux 上一般是一件。
SDL_GetPlatform() 返回的是 Windows,不是 win32 也不是 Windows 10。
它只有四个值:Windows/Linux/macOS/iOS/Android。
所以它只能用来选「用哪套 API」,不能用来判断版本。
pkg-config 那一条是 Linux 侧的万能钥匙:它的输出直接拼进 gcc 命令就行,不用背任何路径。
而且它会把依赖的库也带上——比如 sdl2 会自动带 -lpthread -ldl -lm,漏了这几个符号就找不到。
三平台那张表最后一行最值钱:Windows 上「跑不起来」的九成原因是 DLL 没放对, Linux 上基本不会遇到这个问题。知道这一点,排查方向就定了。
30 秒实验
- 在 Linux 上跑
pkg-config --libs sdl2,看它到底带出了几个库——比你想的多。 - 试着用
pkg-config --exists sdl2 && echo yes判断装没装,这个写法常出现在 configure 脚本里。 - 把
SDL_GetPlatform()的返回值和sys.platform对比,想想各自的适用场景。
常见误区
- 以为装了
libavformat就能编。 那是运行时库,编代码要装libavformat-dev, 否则找不到头文件。 - 以为
pkg-config只是省事。 它还负责带上间接依赖(pthread、dl、m), 漏了就是一堆「未解析的符号」。 - 以为 Windows 和 Linux 的配置思路一样。 Windows 要管「跑时找 DLL」,Linux 不用。 所以 Windows 上「编过了」不等于「能跑」。
自测三问(点开对答案)
1. `libavformat-dev` 和 `libavformat` 有什么区别? —— `-dev` 带头文件和链接用的符号链接,用来编译;不带的只有运行时 so,只能跑不能编。 2. `pkg-config --libs sdl2` 会带出哪些额外库? —— SDL 自己的依赖:pthread、dl、m 等。漏了它们链接会报未解析符号。 3. 为什么 Windows 上「编过了」不等于「能跑」? —— 因为 DLL 是在加载期找的,找不到时程序直接退出,编译链接阶段完全看不出来。 Linux 的 so 在系统路径里,不会遇到。环境三节讲完,回到代码:用 SDL2 直接播一段裸 YUV,把「SDL 只管像素」这句话验证一遍。
- ☐ (本节完,下一节 03.03.05 SDL2播放YUV视频文件)