windows + msys2 编译 ffmpeg,想要保留对应的 avcodec.dll 的话,需要加上 "--enable-shared" 参数,这样生成的 dll 可以在自行开发程序时引入
如果有 enable 三方库的话(比如 x265,比如 libmfx -> for intel QSV HW codec),编译出来的这个 avcodec.dll ,会依赖于三方的 dll (libx265.dll,libmfx-1.dll)才能运行
如果把第三方库的内容,一起打包进 ffmpeg 对应的 dll (比如 avcodec.dll)中,这样子生成的 avcodec.dll 就不会再依赖于三方 dll 了
想要达到这个目标,需要在 config 时,加上static link 的参数:--extra-ldflags=-static --pkg-config-flags=--static
完整的命令如下:
./configure --enable-shared --enable-libx265 --enable-gpl --enable-libmfx --enable-ffnvcodec --enable-nvdec --enable-nvenc --extra-cflags=-I/d/msys64/mingw64/include/mfx --extra-ldflags=-L/d/msys64/mingw64/lib --extra-ldflags=-static --pkg-config-flags=--static
可惜的是,如果有 enable libmfx 的话,上面的 config 指令会报错,提示找不到 libmfx
查看对应的 config log (E:\ffmpeg\ffmpeg-master\ffbuild\config.log),会发现下面的异常:
gcc -L/d/msys64/mingw64/lib -static -Wl,--nxcompat,--dynamicbase -Wl,--high-entropy-va -Wl,--as-needed -Wl,--image-base,0x140000000 -o /tmp/ffconf.7AG0j4aL/test.exe /tmp/ffconf.7AG0j4aL/test.o -lmfx -lstdc++ -lole32 -luuid
D:/MinGW/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: D:/msys64/mingw64/lib\libmfx.a(libmfx_la-mfx_plugin_hive.o):(.text+0x3c): undefined reference to `__imp_swscanf_s'
(使用 visual studio 来编译libmfx 源代码生成的 libmfx.dll 也有这个问题...)
网上搜索,找到在 visual studio 下的解决方案:编译时,添加链接 "legacy_stdio_definitions.lib" 这个lib
翻了下这个 lib 对应的 cpp 文件(D:\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\crt\src\linkopts\legacy_stdio_definitions.cpp),里面重新定义了 __imp_swscanf_s 这个函数:
#ifdef _M_IX86
#define _VCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(f) _CRT_CONCATENATE(_imp__, f)
#else
#define _VCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(f) _CRT_CONCATENATE(__imp_, f)
#endif
#define _VCRT_DEFINE_IAT_SYMBOL(f) \
extern "C" __declspec(selectany) void const* const _VCRT_DEFINE_IAT_SYMBOL_MAKE_NAME(f) \
= reinterpret_cast<void const*>(f)
_VCRT_DEFINE_IAT_SYMBOL(swscanf_s);
其实就是用 reinterpret_cast 指向 swscanf_s 这个函数了。swscanf_s 这个是 C 的标准库函数,定义在头文件 <wchar.h> 中
但是,msys2 中使用 Mingw gcc/g++ 编译的话,并没有现成的 "legacy_stdio_definitions.lib" 可以直接用,它是 visual studio 自带的
Mingw gcc/g++ 中,可以参考 visual studio 的做法,自己用 g++ 重新生成一个 lib 文件,包含 __imp_swscanf_s 的定义就好了。做法如下:
- 新建 cpp 文件:legacy_stdio_definitions.cpp,文件内容如下。因为这里只有这一个函数出问题,就只定义了这一个,如果有遇到其他函数出问题的,可以再加上去
-
#include <wchar.h> extern "C" void const* const __imp_swscanf_s = reinterpret_cast<void const*>(swscanf_s);
-
- 用上面的 cpp 文件生成对应的 lib 文件,gcc/g++ 下面,就是后缀 ".a" 的文件
-
g++ -c legacy_stdio_definitions.cpp -o legacy_stdio_definitions.o /d/MinGW/mingw64/bin/ar.exe r liblegacy_stdio_definitions.a legacy_stdio_definitions.o
会在对应目录下生成想要的文件:liblegacy_stdio_definitions.a
-
- 把上面生成的 liblegacy_stdio_definitions.a 文件拷贝到 msys2 mingw64 lib 目录下(D:\msys64\mingw64\lib),和其他的 lib 放在一起
- 因为是 libmfx 出现问题,所以修改一下 libmfx 的 pc 文件,多链接上面的 lib
- 修改文件:D:\msys64\mingw64\lib\pkgconfig\libmfx.pc
- Libs 那一行最后多加上"-llegacy_stdio_definitions"
-
Libs: -L${libdir} -lmfx -lstdc++ -lole32 -luuid -llegacy_stdio_definitions
- 重新 configure 就可以 Pass 了..