Loading... ## 背景 近期在做一个音视频项目通过如下方式引入FFmpeg: ```cmake set(FFMPEG_LIBS avformat avcodec avutil swresample swscale) find_library(FFmpeg_FOUND NAMES ${FFMPEG_LIBS} HINTS "${FFMPEG_PREFIX_PATH}/lib/" REQUIRED) ... target_link_libraries(${PROJECT_NAME} PRIVATE ${FFmpeg}) ``` 然而在链接阶段,链接器提示找不到符号。 ## 原因 根据 cmake 的文档 > This command is used to find a library. A cache entry, or a normal variable if `NO_CACHE` is specified, named by `<VAR>` is created to store the result of this command. https://cmake.org/cmake/help/latest/command/find_library.html 意味着`find_library`一次只能找到一个库,而`NAMES`是用来指定同一个库可能的名称: > Specify one or more possible names for the library. 因此文章开始的代码只会链接 `avformat`。 ## 解决 一种显然的解决方案是使用`foreach`循环`${FFMPEG_LIBS}`依此链接: ```cmake set(FFmpeg) foreach(LIB IN LISTS FFMPEG_LIBS) find_library(FFmpeg_FOUND NAMES ${LIB} HINTS "${FFMPEG_PREFIX_PATH}/lib/" REQUIRED) list(APPEND FFmpeg "${FFmpeg_FOUND}") endforeach() ... target_link_libraries(${PROJECT_NAME} PRIVATE ${FFmpeg}) ``` 然而,这种做法并不可行,结果同文章开始的代码结果一致。在不指定`NO_CACHE`的情况下,`cmake`并不会每次都去搜索相应的库,而是在第一次搜索之后,后续的`find_library`直接给变量赋值。为了性能,我们最好不要指定`NO_CACHE`。一种解决方案是使用不同的变量名: ```cmake set(FFmpeg) foreach(LIB IN LISTS FFMPEG_LIBS) find_library(FFmpeg_FOUND_${LIB} NAMES ${LIB} HINTS "${FFMPEG_PREFIX_PATH}/lib/" REQUIRED) list(APPEND FFmpeg "${FFmpeg_FOUND_${LIB}}") endforeach() ... target_link_libraries(${PROJECT_NAME} PRIVATE ${FFmpeg}) ``` 删除cmake的缓存(如果使用clion通常是`cmake-build-debug`),重载项目即可解决问题。 最后修改:2022 年 04 月 18 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏