编译启用libx264的FFmpeg后,本地C++项目链接出现未定义引用错误的求助
解决本地Ubuntu 22+下FFmpeg+x264+VAAPI链接错误问题
我帮你梳理下这个问题的核心原因和解决步骤——云端环境干净所以能正常编译,本地出问题基本是CMake配置逻辑错误或者系统残留库干扰导致的,咱们一步步来解决:
一、先排查本地环境残留问题
虽然你卸载了系统FFmpeg,但可能还有残留的库或者配置文件干扰:
- 检查系统目录里的FFmpeg库:
如果发现/usr/lib下还有旧的FFmpeg库,直接删除(注意备份,避免误删);ls /usr/lib/x86_64-linux-gnu/libav*.so* ls /usr/local/lib/libav*.so* - 清理pkg-config残留配置:
sudo rm -rf /usr/lib/pkgconfig/libav*.pc /usr/local/lib/pkgconfig/libav*.pc - 重新更新共享库缓存:
sudo ldconfig
二、修复CMakeLists.txt的核心错误
你的CMake配置有几个明显的逻辑问题,这是导致链接错误的主要原因:
- 错误地在
add_definitions里放链接参数:add_definitions是用来添加编译宏的,-lxxx这类链接参数放在这里不会生效,反而会干扰编译; - 重复查找库:
AVCODEC_INCLUDE_DIR和AVCODEC_LIBRARY被查找了两次,容易导致混淆; - 库链接顺序错误:GCC链接器要求被依赖的库放在后面,比如avcodec依赖x264,x264要放在avcodec之后链接,手动写链接参数很容易搞反顺序;
- 未优先查找自己编译的FFmpeg库:默认的
find_library可能先找到系统残留的库,而不是你编译的/usr/local/lib下的库。
修改后的CMakeLists.txt示例
cmake_minimum_required(VERSION 3.7) project(Renderer C CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin) # 仅保留编译宏定义,编译选项单独设置 add_definitions(-DGL_SILENCE_DEPRECATION) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") # 将调试符号选项放在编译flags里 # 设置pkg-config路径,优先查找本地编译的FFmpeg配置文件 set(PKG_CONFIG_PATH "/usr/local/lib/pkgconfig:$ENV{PKG_CONFIG_PATH}") # 使用pkg-config自动查找依赖(比手动find更可靠,能自动处理链接顺序) find_package(PkgConfig REQUIRED) pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET libavformat libavcodec libavutil libswscale libswresample libavdevice ) pkg_check_modules(X264 REQUIRED IMPORTED_TARGET libx264) pkg_check_modules(VA REQUIRED IMPORTED_TARGET libva libva-drm libva-x11) # 查找线程库 set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) # 查找OpenGL、X11等图形依赖 find_package(OpenGL REQUIRED) find_package(X11 REQUIRED) # 替换为你实际的源文件列表 list(APPEND SOURCES # 这里写你的源文件,比如 src/xxx.cpp ) add_executable(Renderer src/main.cpp src/Application.cpp src/Application.h ${SOURCES}) # 设置头文件包含路径 target_include_directories(Renderer PRIVATE ${OPENGL_INCLUDE_DIR} ${X11_INCLUDE_DIR} ) # 链接库,严格遵循"依赖多的在前,被依赖的在后"的顺序 target_link_libraries(Renderer PRIVATE Threads::Threads ${OPENGL_LIBRARIES} ${X11_LIBRARIES} PkgConfig::FFMPEG PkgConfig::X264 PkgConfig::VA -lz -lm -lbz2 -llzma -lrt -lvdpau )
关键修改点说明
- 用pkg-config管理依赖:自己编译的FFmpeg会生成
.pc配置文件,pkg-config能自动获取正确的头文件路径、库路径和链接顺序,彻底避免手动配置的错误; - 分离编译和链接选项:把
-g这类编译选项放到CMAKE_CXX_FLAGS,链接参数全部放到target_link_libraries; - 指定PKG_CONFIG_PATH:确保优先找到你编译的FFmpeg的配置文件,而不是系统残留的;
- 规范链接顺序:pkg-config生成的目标已经处理了FFmpeg内部的依赖顺序,只需要把外部依赖(比如x264、VAAPI)放在FFmpeg之后即可。
三、重新编译验证
- 删除旧的build目录(如果有的话):
rm -rf build && mkdir build && cd build - 生成CMake配置,注意查看输出,确认找到的是
/usr/local/lib下的FFmpeg库:
比如你应该看到类似cmake ..Found libavcodec: /usr/local/lib/libavcodec.so的输出; - 编译项目:
make -j$(nproc) - 验证链接是否正确:
检查输出里的FFmpeg、x264、VAAPI库是否都指向ldd ../bin/Renderer/usr/local/lib或者正确的路径。
四、额外排查点(如果还是有问题)
- 检查FFmpeg编译配置:重新运行
./configure --enable-shared --enable-libx264 --enable-gpl,确认输出里有libx264: yes和VAAPI: yes,确保这些功能真的被编译进去了; - 对比云端和本地的gcc版本:如果云端是gcc10,本地是gcc12,可能存在ABI差异,可以尝试安装对应版本的gcc;
- 确认libx264-dev安装正确:检查
/usr/lib/x86_64-linux-gnu/libx264.so和/usr/include/x264.h是否存在。
内容的提问来源于stack exchange,提问作者Turgut
相关产品推荐
相关产品推荐

