预编译spdlog(含外部fmt库)编译报错:spdlog/fmt/fmt.h头文件未找到
问题描述
开发环境:Windows 10 + MSYS2 GCC
需求:在项目中使用依赖外部fmt库的预编译spdlog
已执行操作:
- 编译spdlog:
git clone https://github.com/gabime/spdlog.git cd spdlog && mkdir build && cd build cmake -DSPDLOG_FMT_EXTERNAL=ON .. && ninja
- 文件复制:
- 将spdlog/build下的生成文件复制到项目目录
MY_PROJECT/spdlog_precompiled - 将spdlog根目录下的
include文件夹复制到MY_PROJECT目录(该目录包含spdlog/fmt/fmt.h)
- 将spdlog/build下的生成文件复制到项目目录
- 项目CMakeLists.txt配置(
NAME为目标名称):
set(spdlog_DIR ${CMAKE_SOURCE_DIR}/spdlog_precompiled) find_package(spdlog REQUIRED) target_link_libraries( ${NAME} spdlog::spdlog $<$<BOOL:${MINGW}>:ws2_32>) target_include_directories(${NAME} ${CMAKE_SOURCE_DIR}/include)
编译错误信息:
C:/Development/Spirallo/WinCanSpiralloComponent/src/spirallolib/DebugLog.hpp:10:10: fatal error: spdlog/fmt/fmt.h: No such file or directory 10 | #include "spdlog/fmt/fmt.h" | ^~~~~~~~~~~~~~~~~~
即使在顶层CMakeLists.txt添加include_directories(include),错误仍存在。
问题分析与解决
核心错误点
SPDLOG_FMT_EXTERNAL=ON的本质误解:启用该选项后,spdlog不会内置fmt代码,仅提供spdlog/fmt/fmt.h作为转发头文件,实际需要依赖独立编译的外部fmt库的头文件和库文件,你未引入外部fmt的依赖。- CMake配置语法错误:
target_include_directories缺少PRIVATE/PUBLIC/INTERFACE关键字,CMake会忽略这条配置,导致复制的include路径未被正确添加到目标编译路径中。 - 预编译spdlog的依赖缺失:编译spdlog时未指定外部fmt的路径,生成的spdlog配置文件无法正确关联fmt,后续项目中
find_package(spdlog)也无法自动引入fmt依赖。
修正步骤
1. 先编译并引入外部fmt库
# 克隆fmt仓库并编译 git clone https://github.com/fmtlib/fmt.git cd fmt && mkdir build && cd build cmake .. && ninja # 复制文件到项目目录 # 将build下的生成文件复制到 MY_PROJECT/fmt_precompiled # 将fmt根目录的include/fmt文件夹复制到 MY_PROJECT/include/fmt
2. 重新编译spdlog(关联外部fmt)
cd spdlog/build rm -rf * # 清空之前的编译产物 # 指定外部fmt的路径,再编译spdlog cmake -DSPDLOG_FMT_EXTERNAL=ON -DFMT_DIR=/path/to/MY_PROJECT/fmt_precompiled .. && ninja # 重新复制spdlog/build的生成文件到 MY_PROJECT/spdlog_precompiled
3. 修正项目CMakeLists.txt配置
# 先引入外部fmt set(fmt_DIR ${CMAKE_SOURCE_DIR}/fmt_precompiled) find_package(fmt REQUIRED) # 引入预编译的spdlog set(spdlog_DIR ${CMAKE_SOURCE_DIR}/spdlog_precompiled) find_package(spdlog REQUIRED) # 链接目标,同时关联fmt和spdlog target_link_libraries( ${NAME} PRIVATE spdlog::spdlog fmt::fmt $<$<BOOL:${MINGW}>:ws2_32> ) # 修正include路径配置,添加关键字 target_include_directories(${NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
额外说明
如果项目中#include "spdlog/fmt/fmt.h"是为了使用fmt的API,更推荐直接#include <fmt/core.h>——启用外部fmt后,spdlog的转发头文件仅用于兼容旧代码,直接使用fmt原生头文件更规范。
内容的提问来源于stack exchange,提问作者Paweł Kłeczek
相关产品推荐
相关产品推荐

