Windows 上编 FFmpeg 只有三条路:MSVC、MinGW、Cygwin。 MinGW 是「GNU 工具链 + 原生 PE」,不加 POSIX 层,所以产物要靠几个 gcc 运行时 DLL。
1.2 整节都在讲 Windows 编译,这一篇先认路。 下一篇装 MSYS2,那是 MinGW 在 Windows 上的落地形态。
一、三条路,一句话一条
同样一句 #include <libavcodec/avcodec.h>,三条路编出来的东西完全不能互换。
环境 编译器 导入库 运行时依赖
MSVC cl.exe avcodec.lib VC 运行时,系统自带 MinGW gcc.exe libavcodec.dll.a libgcc_s_seh-1.dll 等 Cygwin gcc.exe libavcodec.dll.a cygwin1.dll(POSIX 层)
MinGW 与 Cygwin 的差别只有一个词:POSIX 层。
MinGW 让 gcc 直接生成 Windows 原生的 PE 文件,程序跑起来跟 cl 编的一样快;
Cygwin 在中间垫了一层,把 Linux 的系统调用翻译成 Windows 的,所以 fork() 能用,
代价是每个程序都得拖着 cygwin1.dll。
编 FFmpeg 用 MinGW,不用 Cygwin。 因为 FFmpeg 不依赖 fork(),
垫那一层纯属给自己找麻烦——多一个 DLL 要分发,还慢一截。
二、Minimalist 到底省了什么
MinGW 全名 Minimalist GNU for Windows,省的是「模拟」两个字。
它只提供三样东西:GNU 的编译器(gcc、g++)、GNU 的构建工具(make、binutils)、
Windows 自己的 C 运行库(msvcrt 或 ucrt)。不提供 POSIX 头文件,不提供进程模拟。
代价写在产物上:
MinGW 编出来的 DLL 默认动态链接三个 gcc 运行时——libgcc_s_seh-1.dll(异常处理)、
libstdc++-6.dll(C++ 标准库)、libwinpthread-1.dll(线程)。
这三个不在系统里,得跟着你的程序一起发。
这就是「MinGW 产物拷到别人机器上就报缺 DLL」的全部原因。 不是 FFmpeg 的锅,
是编译器运行时的锅。
三、本机一条路都走不了
下面这张表是本机十条命令的真实结果: 命令 结果
cl / cl.exe 不在 PATH gcc / g++ 不在 PATH clang 不在 PATH make / nmake 不在 PATH pacman 不在 PATH cmake / qmake 不在 PATH git D:\WorkBuddy\resources\vendor\PortableGit\mingw64\bin\git.EXE
十条里只有 git 找得到。 而这台机器上装着 Python 与 PyAV,能跑转码、
能做滤镜——它是「用 FFmpeg 的机器」,不是「编 FFmpeg 的机器」。
判断一台机器属于哪一类,看一样东西就够:有没有 libavcodec/avcodec.h。
有头文件,能开发;只有 DLL,只能运行。PyAV 给的是后者。
四、选哪条路:三个问题定下来
一问:要不要发版给别的机器? 要,选 MSVC——VC 运行时在新版 Windows 上都自带。 二问:团队里有没有 VS 授权? 没有,选 MinGW——免费,代价是带三个 DLL。 三问:已有的工程用哪条? 跟着它——混链没有中间状态,只有全崩。 三条路都能编出功能完整的 FFmpeg,差别只在产物格式与分发成本。 教材走的是 MinGW 与 MSVC 两套都讲,本课照它的顺序走。
五、动手 Demo:三条 Windows 编译路,本机一条都没有
先摆对照表,再用 shutil.which 把本机逐条查一遍。
查不到不是错,是这台机器的定位不同。
import shutil
tools = ["cl", "gcc", "g++", "clang", "make",
"nmake", "pacman", "pkg-config", "cmake", "git"]
for t in tools:
print("%-12s %s" % (t, shutil.which(t)))
实跑输出:
--------------------------------------------------------------------
MinGW 是什么——三条 Windows 上的编译路,本机一条都没有
--------------------------------------------------------------------
**① 三条路的区别,一句话一条**
环境 编译器 产物 代价
--------------------------------------------------------------------------------
MSVC cl.exe .lib + .dll 商业授权,与 VC 运行时绑死
MinGW gcc.exe .dll.a + .dll 免费,产物依赖 libgcc 系列 DLL
Cygwin gcc.exe .dll + cygwin1.dll 跑在 POSIX 层上,慢且难分发
**MinGW 的意思是 Minimalist GNU for Windows**:把 GNU 那套工具(gcc、make、
binutils)搬到 Windows 上,但**不加 POSIX 模拟层**,直接生成原生 PE 文件。
Cygwin 加了那层,所以能跑 `fork()`,代价是每个程序都得拖着 `cygwin1.dll`。
**② 本机走哪条路?哪条都走不了**
命令 找到的路径
--------------------------------------------------------------------------------
cl (不在 PATH 里)
gcc (不在 PATH 里)
g++ (不在 PATH 里)
clang (不在 PATH 里)
make (不在 PATH 里)
nmake (不在 PATH 里)
pacman (不在 PATH 里)
pkg-config (不在 PATH 里)
cmake (不在 PATH 里)
git D:\WorkBuddy\resources\vendor\PortableGit\mingw64\bin\git.EXE
十条命令里只有 **1 条**找得到:git。
**③ 这不是配错了,是这台机器的定位不同**
它装的是 Python 与 PyAV:**库是编好的,头文件没有,编译器也没有**。
拿它写 Python 调用 av 足够,
拿它做 SDK 二次开发一步也走不了——因为二次开发要 `#include <libavcodec/avcodec.h>`,
而这个头文件在机器上根本不存在。
**④ 一句能记住的话**
**装了一个「库」不等于能开发,能开发的标志是「有头文件 + 有导入库」。**
PyAV 给的是运行时,不是开发包。这条区别,是整章存在的理由。
十条命令只有 git 在,其余全是 None。 这条结果说明本机属于「运行 FFmpeg」那一类,不是「编译 FFmpeg」那一类。
30 秒实验
where cl与where gcc两条命令,看是不是都回「找不到」。- 找一个装着 VS 的同事,在他的「开发者命令提示符」里敲
cl,看第一行有没有版本号。 python -c "import av, os; print(os.path.dirname(av.__file__))",进那个目录数一下有几个 .h 头文件——数出来是 0。
常见误区
- 以为装了 VS 就有 cl。 cl 只在「开发者命令提示符」那套环境变量里,普通 cmd 里找不到。
- 拿 Cygwin 编 FFmpeg。 多一层 POSIX 模拟,产物还得带 cygwin1.dll,没有任何好处。
- 以为 MinGW 产物是绿色免安装的。 它要靠三个 gcc 运行时 DLL,不一起发就报缺 DLL。
自测三问(点开对答案)
1. MinGW 与 Cygwin 最关键的区别是什么? —— 有没有 POSIX 模拟层。MinGW 直接生成原生 PE,Cygwin 垫一层把 Linux 系统调用翻译成 Windows。 2. 为什么 MinGW 编出来的程序在别人机器上常报缺 libgcc_s_seh-1.dll? —— 因为 MinGW 默认动态链接 gcc 的运行时。可以 configure 时静态链进去,或发版时把三个 DLL 一起打包。 3. 怎么一句话判断一台机器能不能做 FFmpeg 二次开发? —— 看它有没有 libavcodec/avcodec.h。有头文件才能编自己的程序,只有 DLL 只能跑现成的东西。- ☐ (本节完,下一节 1.2.2 安装 MSYS2)