使用CMake链接FFmpeg静态库仍遇函数未定义引用问题
静态链接FFmpeg静态库时出现未定义引用错误排查
问题场景
自定义编译FFmpeg静态库(.a)并集成到CMake项目后,始终出现链接错误:
CMakeFiles/ffmpegtest.dir/main.cpp.obj:main.cpp:(.text+0xc): undefined reference to avformat_alloc_context
已将项目简化至最简结构,问题仍未解决。
项目代码
main.cpp
extern "C" { #include <libavutil/frame.h> #include <libavutil/mem.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> } int main(){ avformat_alloc_context(); return 0; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.24) project(ffmpegtest) add_executable(ffmpegtest main.cpp) find_library(AVCODEC_LIB avcodec PATHS lib/ffmpeg/lib) find_library(AVFORMAT_LIB avformat PATHS lib/ffmpeg/lib) find_library(AVUTIL_LIB avutil PATHS lib/ffmpeg/lib) find_library(AVDEVICE_LIB avdevice PATHS lib/ffmpeg/lib) target_include_directories(ffmpegtest PRIVATE lib/ffmpeg/include ) target_link_libraries(ffmpegtest ${AVCODEC_LIB} ${AVFORMAT_LIB} ${AVUTIL_LIB} ${AVDEVICE_LIB} )
FFmpeg编译配置脚本
./configure \ --disable-doc \ --enable-static \ --prefix=${ffmpegBuildDir}
注:ffmpegBuildDir为自定义编译输出目录,已将该目录下的.a文件复制到测试项目对应路径。
补充信息
CMake生成的链接命令
C:\WINDOWS\system32\cmd.exe /C "cd . && C:\devkitPro\msys2\mingw32\bin\c++.exe CMakeFiles/ffmpegtest.dir/main.cpp.obj -o ffmpegtest.exe -Wl,--out-implib,libffmpegtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0 D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavcodec.a D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavformat.a D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavutil.a D:/Programming/ffmpegtest/lib/ffmpeg/lib/libavdevice.a -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ." C:/devkitPro/msys2/mingw32/bin/../lib/gcc/i686-w64-mingw32/14.2.0/../../../../i686-w64-mingw32/bin/ld.exe: CMakeFiles/ffmpegtest.dir/main.cpp.obj:main.cpp:(.text+0xc): undefined reference to avformat_alloc_context
nm命令输出(检查libavformat.a符号)
U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context 0000000000000390 T avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context U avformat_alloc_context
问题原因
从nm输出可以确认libavformat.a中确实存在avformat_alloc_context的定义(T标记表示该符号是文本段的函数定义),链接错误的核心原因是静态库的链接顺序不符合GCC链接器规则:
GCC链接器处理静态库时,会按从左到右的顺序遍历库,仅提取当前未解决符号所需的目标文件。如果被依赖的库放在依赖它的库前面,链接器处理前面的库时没有未解决符号,不会提取任何内容,后续处理依赖库时就会找不到需要的符号。
FFmpeg各库的依赖关系为:
- avdevice 依赖 avformat、avutil
- avformat 依赖 avcodec、avutil
- avcodec 依赖 avutil
当前CMake的链接顺序是avcodec -> avformat -> avutil -> avdevice,完全颠倒了依赖顺序,导致链接器无法正确解析符号。
解决方法
方法1:修正链接顺序
修改CMakeLists.txt中的target_link_libraries,按依赖链从上层到下层的顺序排列(即先写依赖其他库的库,再写被依赖的库):
target_link_libraries(ffmpegtest ${AVDEVICE_LIB} ${AVFORMAT_LIB} ${AVCODEC_LIB} ${AVUTIL_LIB} )
方法2:用pkg-config自动管理链接(推荐)
利用FFmpeg自带的pkg-config配置文件自动处理依赖和链接顺序,避免手动排序出错:
cmake_minimum_required(VERSION 3.24) project(ffmpegtest) add_executable(ffmpegtest main.cpp) # 查找pkg-config find_package(PkgConfig REQUIRED) # 查找FFmpeg库 pkg_check_modules(FFMPEG REQUIRED libavformat libavcodec libavutil libavdevice) # 添加头文件路径 target_include_directories(ffmpegtest PRIVATE ${FFMPEG_INCLUDE_DIRS}) # 链接FFmpeg库(pkg-config自动处理顺序) target_link_libraries(ffmpegtest ${FFMPEG_LIBRARIES})
注:需确保FFmpeg编译时生成了pkg-config文件(默认会生成,位于${ffmpegBuildDir}/lib/pkgconfig),并将该路径添加到环境变量PKG_CONFIG_PATH中。
额外检查项
- 确认编译FFmpeg的编译器与项目使用的编译器架构一致(本例中均为mingw32 x86,不能混用MSVC或x64编译器)
- 确认FFmpeg编译时未禁用avformat模块(当前配置脚本未禁用,无需修改)
内容的提问来源于stack exchange,提问作者MysticTortoise
相关产品推荐
相关产品推荐

