🎬 第一章 编译FFmpeg源码并搭建开发环境
📄 一句话概括

第一次更新要跑两轮,中间还得关窗口重开。 升级时比较版本号不是按字符串比,1.0.9 比 1.0.10 小。

📝 本节和前面几节的关系

装完 MSYS2 的第一件事不是装 gcc,是更新。 更新完才轮到 1.2.4 的 pacman 常用命令。

一、三条命令,别记混

-Sy 只刷新包数据库,-Su 只升级,-Syu 两件一起做。 命令 做什么 什么时候用


pacman -Sy 刷新数据库 想知道有哪些新包 pacman -Su 升级已装的包 数据库已刷新过 pacman -Syu 刷新加升级 日常就用这一条

为什么不能只 -Sy 不 -Su: 数据库说某包是 2.0,而你手上是 1.0, 接下来装一个依赖 2.0 的新包时,pacman 会认为「条件满足」直接装——结果就是半新半旧, 这种状态在 MSYS2 上叫做 partial upgrade,是官方明确不建议的。 这条规矩在 Arch 系上是大忌,MSYS2 沿用了同一套 pacman,规矩一样。

二、为什么第一次要关窗口重开

因为要升级的东西里,包含正在运行的自己。 msys2-runtime 是那层 POSIX 环境的核心,它本身也在升级名单里。 它一换,正在跑的 pacman 就成了「旧核心跑新脚本」,继续往下走会出各种奇怪错误。 所以流程是: pacman -Syu → 提示关窗口 → 重开 → 再 pacman -Su。 第二次跑完没有「请重开」的提示,才算更新完。

三、版本号怎么比:逐段比,不是按字符串比

pacman 的版本号格式是 epoch:pkgver-pkgrel,三段。 比较规则:先比 epoch(没有就当 0),再比 pkgver,最后比 pkgrel; 每一段里按「数字段当数字、字符段当字符」逐个比,谁先分出大小谁赢。 左 右 谁大 关键点


1.2.3-1 1.2.3-2 右 pkgrel 大 1.2.3-1 1.2.10-1 右 10 比 3 大,按数值比 5.1.2-1 5.1.2rc1-1 右 数字段之后还有字符段 2:1.0-1 1:9.9-9 左 epoch 先定胜负 1.0.9-1 1.0.10-1 右 当字符串比会反

最后一行是最值钱的一行。 字符串比较里 1.0.9 大于 1.0.10,因为字符 9 大于 1; 按段比较里 10 是数字十,就是比 9 大。写升级脚本、写自己的版本判断,栽在这一处的次数最多。 本机 Demo 里这五组全部与预期一致,比较器是本课自己写的,规则照 pacman 的 vercmp 复原。

四、更新之后先验三样

更新跑完不等于环境好了,三样都要验: 验什么 命令 期望


pacman 本身 pacman -Q pacman 有版本号 gcc 能不能跑 gcc --version 第一行有版本 make 在不在 make --version GNU Make 4.x

第三条常被忽略:make 的版本太老会让 FFmpeg 的 Makefile 解析出错,报的错却指向某个变量。 看见莫名其妙的 make 报错,先 make --version。

五、动手 Demo:更新 MSYS2——为什么第一次必须更新三遍

本机没有 pacman,所以这一段做的是「把 vercmp 的规则写出来跑一遍」。 五组对照全部断言,错一组就不会往下走。

def key(v):
    epoch, rest = (v.split(":", 1) + ["0"])[:2] if ":" in v else ("0", v)
    pkgver, pkgrel = (rest.rsplit("-", 1) + ["0"])[:2]
    # 每段再切成「数字段 / 字符段」交替的序列
    ...

assert cmp("1.0.9-1", "1.0.10-1") == -1

实跑输出:

--------------------------------------------------------------------
更新 MSYS2——为什么第一次必须更新三遍
--------------------------------------------------------------------

**① 更新分三段,不是一条命令跑完**

  步     命令            干什么
  ---------------------------------------------------
  1      pacman -Sy      只刷新包数据库,不装东西
  2      pacman -Su      按新数据库升级已装的包
  3      pacman -Syu     两件一起做,最常用

**为什么第一次要重开窗口再更新一遍**:MSYS2 的核心包 `msys2-runtime` 自己也在升级名单里,它一换,
正在跑的 pacman 就成了「用旧核心跑新脚本」,所以程序会让你关窗口,
重开后 `pacman -Su` 把剩下的装完。

**② pacman 的版本号比较规则,是个真坑**

格式是 `epoch:pkgver-pkgrel`,比较时**从左往右按段比,数字段按数值比、字符段按字典序比**,
谁先分出大小谁赢。下面这套比较器是本课自己写的,规则跟 pacman 的 vercmp 一致。

  左          右             谁大     为什么
  ----------------------------------------------
  1.2.3-1     1.2.3-2        右赢     逐段比
  1.2.3-1     1.2.10-1       右赢     逐段比
  5.1.2-1     5.1.2rc1-1     右赢     逐段比
  2:1.0-1     1:9.9-9        左赢     逐段比
  1.0.9-1     1.0.10-1       右赢     逐段比

五组全部与预期一致——特别是 `1.0.9` 小于 `1.0.10` 这一组,**把它当字符串比就会比反**,
这是升级脚本写错最常见的一处。

**③ 更新完先别急着编**

`pacman -Q gcc` 看版本,`gcc --version` 看能不能跑。
两条都对了,再动 FFmpeg 的源码目录,否则 configure 报的错你分不清是源码问题还是工具链没装好。

五组断言全过,说明这套比较器与 pacman 的规则一致。 最后一组是最关键的:按字符串比会把结论比反。

30 秒实验

  1. 在装好的 MSYS2 里敲 pacman -Q pacman,再用 pacman -Qi pacman 看依赖。
  2. 把 1.0.9 与 1.0.10 两个字符串直接 > 比较,看 Python 给出什么结果——和版本比较的结论正好相反。
  3. pacman -Syu 跑到提示重开时,先别关,看看报了什么,再关窗口重开跑 -Su。

常见误区

  1. 只跑 -Sy 不跑 -Su。 数据库新、包旧,接下来装任何东西都可能装出半新半旧的状态。
  2. 更新时不关窗口。 msys2-runtime 升级后旧核心跑新脚本,会出各种奇怪错误。
  3. 用字符串比较版本号。 1.0.9 会被判成比 1.0.10 大,升级判断直接反掉。
自测三问(点开对答案) 1. 为什么第一次更新要关窗口重开? —— 因为要升级的 msys2-runtime 是正在运行的那层核心,换掉它之后旧进程跑新脚本会出错。 2. `1.0.9` 与 `1.0.10` 哪个新?为什么字符串比较会得出相反结论? —— 1.0.10 新。字符串比较逐字符比,`9` 大于 `1`,所以在第三位就分出胜负;版本比较把 10 当数字十。 3. `-Sy` 单独用有什么风险? —— 数据库刷新了但包没升级,接下来装的包若依赖新版,会形成半新半旧的 partial upgrade 状态。

相关笔记