Qt 的 .pro 里只要写三行:头文件路径、库路径、库名。
三行里三个坑:-l 前缀、-L 顺序、工具链一致。
1.3 把库装好了,这一篇让 Qt 认得它。 下一篇 1.5 是同一件事的 VS 版本。
一、三行就能编,但三行都能写错
Qt 的工程文件是 .pro,本质是一堆变量赋值。
变量 写什么 作用
INCLUDEPATH 头文件目录 让 #include 找得到 LIBS -L 库目录 -l 库名 让链接器找得到 DEPENDPATH 头文件目录 改头文件时触发重编
三行都写对才编得过。 少 INCLUDEPATH,报「找不到头文件」;少 LIBS,报「未定义引用」; 少 DEPENDPATH 不报错,但你改了头文件它不重编,查半天以为是代码问题。
二、坑一:-lavcodec 不是 -llibavcodec
-l 后面的名字要去掉 lib 前缀与 .so/.a 后缀。
库文件 正确的写法 错误的写法
libavcodec.so -lavcodec -llibavcodec libavformat.so -lavformat -llibavformat avcodec.lib 不能这样写 Qt 不认 MSVC 库
写 -llibavcodec,链接器会去找 liblibavcodec.so。 报错信息是 cannot find -llibavcodec,
看着像装错了库,其实是名字多写了三个字母。
三、坑二:-L 必须在 -l 前面
链接器从左往右扫,遇到 -l 当场就要找到它。
所以 -lavcodec -L/path 这种写法,-L 等于没写——扫到 -lavcodec 时它还不知道去哪找。
写法 结果
-L/path -lavcodec 对 -lavcodec -L/path 错的,找不到库
这条规则跟「先声明再使用」是一个意思,只是链接器不报语法错,只报「找不到这个库」。
看见 cannot find -lavcodec,先看 -L 是不是写在后面了。
四、坑三:构建套件要与库同一工具链
Qt 的「构建套件」决定用哪个编译器,它必须与编 FFmpeg 的那个一致。 Qt 套件 能链哪种 FFmpeg 混了会怎样
MinGW 版 Qt MinGW 编的 报 undefined reference MSVC 版 Qt MSVC 编的 报 LNK2019
这两套 Qt 装在同一台机器上很常见,装的时候不觉得,编的时候才发现套件选错了。
判断方法: Qt Creator 的「构建套件」里能看到编译器名字,gcc 就是 MinGW,
cl.exe 就是 MSVC。
本机验不了这一节:没有 Qt、没有 Qt Creator、qmake 不在 PATH。
上面三个坑是规则,不依赖环境。
五、动手 Demo:Qt 开发环境——.pro 里三行写错,编译就找不到库
本机没有 Qt,所以这一段做的是:生成 .pro 片段、检查三处规则、查路径在不在。 路径检查会全报「不在」,规则检查全过。
pro = ["INCLUDEPATH += C:/ffmpeg/include",
"LIBS += -LC:/ffmpeg/lib -lavcodec -lavformat -lavutil"]
print(pro[1].index("-L") < pro[1].index("-lavcodec"))
实跑输出:
--------------------------------------------------------------------
Qt 开发环境——.pro 里三行写错,编译就找不到库
--------------------------------------------------------------------
**① Qt 的工程文件只要三样东西**
`.pro` 里写 `INCLUDEPATH`(头文件在哪)、`LIBS`(导入库在哪)、
`DEPENDPATH`(改头文件时重编的依赖)。少一样就编不过。
**② 本课生成的 .pro 片段**
`INCLUDEPATH += C:/ffmpeg/include`
`LIBS += -LC:/ffmpeg/lib -lavcodec -lavformat -lavutil`
`LIBS += -lavfilter -lswscale -lswresample`
`DEPENDPATH += C:/ffmpeg/include`
**③ 三行里有三个坑,用代码验一遍**
检查项 结果
----------------------------------------
路径存在:C:/ffmpeg/include 不在
路径存在:C:/ffmpeg/lib 不在
-L 在 -l 前面 对
库名带 -l 前缀、不带扩展名 对
**第一个坑:`-lavcodec` 不是 `-llibavcodec`。** `-l` 后面跟的是去掉 `lib` 前缀、去掉扩展名的名字,
写 `-llibavcodec` 链接器会去找 `liblibavcodec.so`。
**第二个坑:`-L` 必须写在用到它的 `-l` 前面。** 链接器是从左往右扫的,先看见 `-l` 再去记 `-L`,
那条路径等于没写。
**第三个坑:Windows 上 `LIBS` 里的库名要跟着工具链变。** MSVC 的导入库叫 `avcodec.lib`,
MinGW 的叫 `libavcodec.dll.a`,Qt 的 `-l` 规则只认后者。
用 MSVC 编 FFmpeg、再用 MinGW 的 Qt 链,必然失败。
**④ 本机验到哪一步**:上面两行路径检查全报「不在」,因为这台机器没编过 FFmpeg。
但**三个坑是规则,不是环境**——路径换对了,规则照样成立。
-L 在前、-l 在后,这一条过了;路径检查两条全不在。
路径不在只说明本机没编过 FFmpeg,不影响规则成立。
30 秒实验
qmake -query QT_INSTALL_PREFIX看 Qt 装在哪,再对一对构建套件的编译器。- 故意把
-L写到-l后面,看链接器报什么。 pkg-config --libs libavcodec看看它给出的顺序,跟自己手写的对一下。
常见误区
- 写
-llibavcodec。 链接器会去找liblibavcodec.so,永远找不到。 - 把
-L写在-l后面。 链接器扫到-l时还不知道去哪找。 - 用 MinGW 版 Qt 链 MSVC 编的 FFmpeg。 两套 ABI 不通用,一个符号都链不上。
自测三问(点开对答案)
1. `-lavcodec` 里的 `-l` 是什么意思,后面的名字怎么来的? —— `-l` 表示链接库,后面的名字是库文件名去掉 `lib` 前缀与扩展名。 2. 为什么 `-L` 必须写在 `-l` 前面? —— 链接器从左往右扫,扫到 `-l` 时就要立刻找到库,后面的 `-L` 来不及起作用。 3. 怎么判断 Qt 套件与 FFmpeg 是不是同一工具链? —— 看套件里的编译器名:gcc 对应 MinGW 编的库,cl.exe 对应 MSVC 编的库。- ☐ (本节完,下一节 1.5 搭建 FFmpeg 的 VS 开发环境)