Issue
I'm building a small project that will output video. I'm trying to link to libswscale to convert RGBA to YUV420, however, the linker ld
cannot successfully find libswscale symbols.
Undefined symbols for architecture x86_64:
"sws_getContext(int, int, AVPixelFormat, int, int, AVPixelFormat, int, SwsFilter*, SwsFilter*, double const*)", referenced from:
VideoWriter::writeFrame(std::__1::vector<char, std::__1::allocator<char> >) in video_writer.cpp.o
The offending line of code is this.
struct SwsContext *sws_ctx = sws_getContext(
avCodecContext->width, avCodecContext->height, AV_PIX_FMT_RGBA,
avCodecContext->width, avCodecContext->height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, NULL, NULL, NULL);
When I use -v on clang I see that the libswscale.dylib is being passed to ld
. The dylib exists on the file system and is the same version as the library's header, as verified by otool
.
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch x86_64 -platform_version macos 10.15.0 11.1 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk -o bin/main -search_paths_first -headerpad_max_install_names CMakeFiles/main.dir/src/main.cpp.o CMakeFiles/main.dir/src/window.cpp.o CMakeFiles/main.dir/src/video_writer.cpp.o -rpath /usr/local/lib /usr/local/lib/libGLEW.2.2.0.dylib /usr/local/lib/libboost_program_options-mt.dylib -framework OpenGL /usr/local/Cellar/sdl2_image/2.6.2/lib/libSDL2_image.dylib /usr/local/lib/libSDL2.dylib /usr/local/Cellar/ffmpeg/5.1.2/lib/libavcodec.dylib /usr/local/Cellar/ffmpeg/5.1.2/lib/libswscale.dylib /usr/local/Cellar/ffmpeg/5.1.2/lib/libavutil.dylib -lc++ -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a -F/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks
This is my cmake file.
cmake_minimum_required(VERSION 3.19.2)
project(FragTool VERSION 1.0)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
# --- c++ build settings --- #
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++ -O0")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_BUILD_TYPE Debug)
# --- dependencies --- #
find_package(GLEW REQUIRED)
find_package(Boost 1.79.0 COMPONENTS program_options REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBAV REQUIRED IMPORTED_TARGET
libavcodec
libswscale
libavutil
)
pkg_check_modules(LIBSDL2 REQUIRED IMPORTED_TARGET
sdl2
sdl2_image
)
set(EXECUTABLE main)
add_executable(${EXECUTABLE} src/main.cpp)
target_sources(${EXECUTABLE} PRIVATE
${CMAKE_SOURCE_DIR}/src/window.cpp
${CMAKE_SOURCE_DIR}/src/video_writer.cpp
)
target_include_directories(${EXECUTABLE} PRIVATE ${CMAKE_SOURCE_DIR}/src)
target_include_directories(${EXECUTABLE} PRIVATE ${GLEW_INCLUDE_DIRS})
target_link_libraries(${EXECUTABLE} PRIVATE GLEW::glew)
target_link_libraries(${EXECUTABLE} PRIVATE ${Boost_LIBRARIES})
target_link_libraries(${EXECUTABLE} PRIVATE PkgConfig::LIBSDL2)
target_link_libraries(${EXECUTABLE} PRIVATE PkgConfig::LIBAV)
I'm stumped as to what could be causing the linker to fail, given that it is being passed the libswscale dylib correctly as far as I can tell. I checked for any other versions of the dylib on the system that maybe are shadowing it, but didn't see any.
Solution
I figured this out. It was because the include statement needed to be wrapped with extern "C"
.
extern "C"
{
#include <libswscale/swscale.h>
}
Answered By - J. Johnson Answer Checked By - Willingham (WPSolving Volunteer)