我已经使用 Homebrew 安装了 ffmpeg(版本 4),并且尝试在 C++ 项目中使用各种 ffmpeg 库,但在链接过程中遇到多个错误。
Undefined symbols for architecture x86_64:
"_av_free", referenced from:
_main in main.cpp.o
"_av_packet_alloc", referenced from:
_main in main.cpp.o
"_av_parser_init", referenced from:
And so on ...
我已包含以下库
extern "C" {
#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavcodec/avcodec.h>
}
但是,这仍然行不通。我想我可能错过了我的
CMakeLists.txt
文件中的某些内容,目前看起来像这样 :
cmake_minimum_required(VERSION 2.6)
project(decode_encode)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-D__STDC_CONSTANT_MACROS")
add_executable(decode_encode main.cpp)
我很可能需要指定额外的链接标志,但是有没有更好的方法来处理
CMakeLists.txt
文件中的链接部分?
PkgConfig 可用于更方便地链接库,如评论中所述。使用 CMake 3.17,这会链接所有 libav 库:
cmake_minimum_required(VERSION 3.17)
project(Foo)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
libavdevice
libavfilter
libavformat
libavcodec
libswresample
libswscale
libavutil
)
add_executable(${PROJECT_NAME}
main.cpp
)
target_link_libraries(${PROJECT_NAME}
PkgConfig::LIBAV
)
好的,我找到了解决方案。 FFmpeg 似乎不支持 CMake 中的 find_package。我必须按照here的建议手动链接库。
最终的 CMakeLists.txt 看起来像这样
cmake_minimum_required(VERSION 2.6)
project(decode_encode)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-D__STDC_CONSTANT_MACROS")
find_path(AVCODEC_INCLUDE_DIR libavcodec/avcodec.h)
find_library(AVCODEC_LIBRARY avcodec)
find_path(AVFORMAT_INCLUDE_DIR libavformat/avformat.h)
find_library(AVFORMAT_LIBRARY avformat)
find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h)
find_library(AVUTIL_LIBRARY avutil)
find_path(AVDEVICE_INCLUDE_DIR libavdevice/avdevice.h)
find_library(AVDEVICE_LIBRARY avdevice)
add_executable(decode_encode main.cpp)
target_include_directories(decode_encode PRIVATE ${AVCODEC_INCLUDE_DIR} ${AVFORMAT_INCLUDE_DIR} ${AVUTIL_INCLUDE_DIR} ${AVDEVICE_INCLUDE_DIR})
target_link_libraries(decode_encode PRIVATE ${AVCODEC_LIBRARY} ${AVFORMAT_LIBRARY} ${AVUTIL_LIBRARY} ${AVDEVICE_LIBRARY})
不过,我确信有更好的方法来聚合所有库。
您需要告诉
CMAKE
在系统中哪里可以找到ffmpeg
的标头和库。
您可以使用 find_package(ffmpeg
来查看您的系统,然后使用它定义的 CMAKE 变量来正确设置编译器的标头和链接器的库。
include_directories(${FFMPEG_INCLUDE_DIRS})
target_link_libraries(decode_encode ${FFMPEG_LIBRARIES})
像下面这样的东西应该能达到目的。
cmake_minimum_required(VERSION 2.6)
project(decode_encode)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-D__STDC_CONSTANT_MACROS")
find_package(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL AVDEVICE REQUIRED) #add here the list of ffmpeg components required
if(FFMPEG_FOUND)
# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers.
# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components.
# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components.
message("FFMPEG_INCLUDE_DIRS = ${FFMPEG_INCLUDE_DIRS} ")
message("FFMPEG_LIBRARIES = ${FFMPEG_LIBRARIES} ")
message("FFMPEG_DEFINITIONS = ${FFMPEG_DEFINITIONS} ")
include_directories(${FFMPEG_INCLUDE_DIRS})
endif()
add_executable(decode_encode main.cpp)
target_link_libraries(decode_encode ${FFMPEG_LIBRARIES})
注意我还没有尝试过这个,所以你可能需要调整它。
有一些非官方的 findFFmpeg 脚本:例如:
https://github.com/snikulov/cmake-modules/blob/master/FindFFmpeg.cmake
但至少在 cmake 3.27 中还没有正式的消息。