Issue
I'm running into something rather weird and I'm not sure how to get to the bottom of it.
I'm using spdlog
as a library. My code is split into two libraries, one called NativeUtils
which is built as a static library and the other is the main library called drivermonitor
. These are Android JNI libraries and are built using Cmake. I'm including my Cmakefiles.
I have a few source files in the NativeUtils
and what I see is that in some files if I call a spdlog function like spdlog::info
I get a linker error however in other files I don't.
: && /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=aarch64-none-linux-android26 --sysroot=/home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-limit-debug-info -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Wl,--gc-sections -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libdrivermonitor.so -o /home/kartik/Projects/DriverMonitor/service/build/intermediates/cxx/Debug/3n3s6c4k/obj/arm64-v8a/libdrivermonitor.so CMakeFiles/drivermonitor.dir/src/AiProcessor.cpp.o CMakeFiles/drivermonitor.dir/src/DriverMonitor.cpp.o CMakeFiles/drivermonitor.dir/src/DriverMonitorNative.cpp.o CMakeFiles/drivermonitor.dir/src/FrameCounter.cpp.o CMakeFiles/drivermonitor.dir/src/NetworkWrapper.cpp.o CMakeFiles/drivermonitor.dir/src/PreProcess.cpp.o CMakeFiles/drivermonitor.dir/test/NativePreProc.cpp.o deps/NativeUtils/libNativeUtils.a /home/kartik/Projects/DriverMonitor/deps/Snpe/lib/arm64-v8a/libSNPE.so /home/kartik/Projects/DriverMonitor/deps/fastcv/lib/arm64-v8a/libfastcv.a /home/kartik/Projects/DriverMonitor/deps/Snpe/lib/arm64-v8a/libc++_shared.so _deps/fmt-build/libfmtd.a _deps/spdlog-build/libspdlogd.a /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/liblog.so /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/libandroid.so /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/libmediandk.so /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/libjnigraphics.so -pthread -llog -lc++_shared /home/kartik/Android/Sdk/ndk/25.1.8937393/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/26/liblog.so -latomic -lm && :
ld: error: undefined symbol: spdlog::details::log_msg::log_msg(spdlog::source_loc, fmt::v10::basic_string_view<char>, spdlog::level::level_enum, fmt::v10::basic_string_view<char>)
>>> referenced by logger.h:134 (_deps/spdlog-src/include/spdlog/logger.h:134)
>>> AImageWrapper.cpp.o:(spdlog::logger::log(spdlog::source_loc, spdlog::level::level_enum, fmt::v10::basic_string_view<char>)) in archive deps/NativeUtils/libNativeUtils.a
Here are my CMakeLists.txt files, My dependencies CMakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(SupportLibs)
find_library(native-media mediandk)
find_library(native-log log)
find_library(native-trace android)
find_library(native-graphics jnigraphics)
include(FetchContent)
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt
GIT_TAG 10.0.0)
FetchContent_Declare(spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog
GIT_TAG v1.12.0)
FetchContent_MakeAvailable(fmt spdlog)
add_subdirectory(Snpe)
add_subdirectory(fastcv)
add_subdirectory(NativeUtils)
I'm using FetchContent
to obtain fmt
and spdlog
.
This is the CMakeLists.txt for NativeUtils
cmake_minimum_required(VERSION 3.22)
project(NativeUtils)
file(GLOB sources src/*.cpp)
file(GLOB headers include/*.hpp)
add_library(NativeUtils STATIC "${sources}" "${headers}")
print_list("${sources}")
target_include_directories(NativeUtils PUBLIC inc)
target_link_libraries(NativeUtils PUBLIC snpe c++_shared)
target_link_libraries(NativeUtils PRIVATE ${native-log} fmt::fmt spdlog::spdlog fastcv)
target_compile_features(NativeUtils PRIVATE cxx_std_17)
I use a GLOB pattern to get the sources and headers. Finally the CMakeLists.txt file for my main library
cmake_minimum_required(VERSION 3.22)
project(DriverMonitor CXX)
macro(print_list)
foreach(arg ${ARGV})
message(" ${arg}")
endforeach()
endmacro()
set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../deps)
add_subdirectory(${distribution_DIR} ${CMAKE_CURRENT_BINARY_DIR}/deps)
file(GLOB headers inc/drivermonitor/*.h)
file(GLOB sources src/*.cpp test/*.cpp)
add_library(drivermonitor SHARED "${headers}" "${sources}")
target_compile_features(drivermonitor PRIVATE cxx_std_17)
target_include_directories(drivermonitor PRIVATE inc)
target_link_libraries(
drivermonitor
PRIVATE
NativeUtils
snpe
fastcv
c++shared
fmt::fmt
spdlog::spdlog
${native-log}
${native-trace}
${native-media}
${native-graphics}
)
I just can't understand why in some source files there is a linker error and in others there isn't, in the same library where all the files are built with the same set of optons.
Solution
There seem a conflict between spdlog and fmt (spdlog make use of fmt), to work around it you can do one of the following:
- Passing -DSPDLOG_FMT_EXTERNAL=ON to Cmake configure command
- Set this in your CMakeLists.txt
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
andset(SPDLOG_FMT_EXTERNAL ON)
before including spdlog
Come across here when looking for solution for similar problem and was able to fix this but I'm not proficient with Cmake to give comprehend answer.
Answered By - Chicky Answer Checked By - Cary Denson (WPSolving Admin)