使用Vcpkg+CMake构建含第三方库的共享库时编译报错求助
单文件CMake配置找不到fmt/color.h的问题排查
问题背景
作为CMake新手,尝试用Vcpkg+CMake构建依赖fmt、spdlog的共享库:
- 单文件CMakeLists.txt配置编译时,出现找不到
fmt/color.h的致命错误 - 改用根目录+子目录的CMake结构时,编译可成功完成
文件结构:
- 根目录下包含
include文件夹、src文件夹 src文件夹内有main.cpp文件
报错的单文件CMakeLists.txt配置
cmake_minimum_required(VERSION 3.28) project(Vcpkg) set (CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(fmt REQUIRED) find_package(spdlog REQUIRED) file(GLOB SOURCES src/*.cpp include/*.hpp) add_library(Vcpkg SHARED ${SOURCES}) add_library(vcpkg::engine ALIAS Vcpkg) target_include_directories(Vcpkg PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) add_executable(akash ${SOURCES}) SET(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 -coverage -fprofile-arcs -ftest-coverage") SET(GCC_COVERAGE_LINK_FLAGS "-coverage -lgcov") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" ) target_compile_features(akash PRIVATE cxx_std_20) target_link_libraries(akash PRIVATE vcpkg::engine fmt::fmt spdlog::spdlog )
错误信息
1/5] Scanning /home/akashdiphazra/Downloads/Vcpkg/src/main.cpp for CXX dependencies FAILED: CMakeFiles/Vcpkg.dir/src/main.cpp.o.ddi /usr/bin/c++ -DVcpkg_EXPORTS -I/home/akashdiphazra/Downloads/Vcpkg/include -I/home/akashdiphazra/Downloads/Vcpkg/src -g -O0 -coverage -fprofile-arcs -ftest-coverage -g -std=gnu++20 -fPIC -fdiagnostics-color=always -E -x c++ /home/akashdiphazra/Downloads/Vcpkg/src/main.cpp -MT CMakeFiles/Vcpkg.dir/src/main.cpp.o.ddi -MD -MF CMakeFiles/Vcpkg.dir/src/main.cpp.o.ddi.d -fmodules-ts -fdeps-file=CMakeFiles/Vcpkg.dir/src/main.cpp.o.ddi -fdeps-target=CMakeFiles/Vcpkg.dir/src/main.cpp.o -fdeps-format=p1689r5 -o CMakeFiles/Vcpkg.dir/src/main.cpp.o.ddi.i /home/akashdiphazra/Downloads/Vcpkg/src/main.cpp:1:10: fatal error: fmt/color.h: No such file or directory 1 | #include <fmt/color.h> | ^~~~~~~~~~~~~ compilation terminated. ninja: build stopped: subcommand failed. make: *** [Makefile:10: debug] Error 1
可成功编译的CMake配置
根目录CMakeLists.txt
cmake_minimum_required (VERSION 3.28) project(Vcpkg) find_package(fmt REQUIRED) find_package(spdlog REQUIRED) # Add sub directories include_directories(include) add_subdirectory(src) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF)
src/CMakeLists.txt
set (CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) SET(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 -coverage -fprofile-arcs -ftest-coverage") SET(GCC_COVERAGE_LINK_FLAGS "-coverage -lgcov") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" ) add_executable(akash main.cpp) target_compile_features(akash PRIVATE cxx_std_20) target_link_libraries(akash fmt::fmt spdlog::spdlog)
问题原因分析
共享库目标未关联依赖:
报错的配置中,仅给可执行文件akash链接了fmt::fmt和spdlog::spdlog,但共享库Vcpkg的源文件(包括main.cpp)同样依赖这些库的头文件。编译共享库目标时,CMake不会自动继承可执行文件的依赖,导致库编译过程无法找到fmt/color.h。重复添加源文件:
把src/*.cpp同时加到共享库Vcpkg和可执行文件akash中,属于重复编译源文件,不仅冗余,还会导致库和可执行文件的编译环境分离,依赖传递失效。成功配置的对比:
可成功的配置没有创建额外的共享库目标,直接给可执行文件akash链接依赖,编译时能直接获取fmt、spdlog的头文件路径,因此不会报错。
修复方案
修改单文件CMakeLists.txt,给共享库目标添加依赖链接,同时避免重复使用源文件:
cmake_minimum_required(VERSION 3.28) project(Vcpkg) set (CMAKE_CXX_STANDARD 20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(fmt REQUIRED) find_package(spdlog REQUIRED) # 仅给库添加源文件(可执行文件只链接库,不重复包含源文件) file(GLOB LIB_SOURCES src/*.cpp include/*.hpp) add_library(Vcpkg SHARED ${LIB_SOURCES}) add_library(vcpkg::engine ALIAS Vcpkg) # 给共享库链接依赖,传递头文件路径 target_link_libraries(Vcpkg PRIVATE fmt::fmt spdlog::spdlog ) target_include_directories(Vcpkg PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) # 可执行文件只需要库的别名,不需要重复源文件 add_executable(akash src/main.cpp) SET(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 -coverage -fprofile-arcs -ftest-coverage") SET(GCC_COVERAGE_LINK_FLAGS "-coverage -lgcov") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" ) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" ) target_compile_features(akash PRIVATE cxx_std_20) target_link_libraries(akash PRIVATE vcpkg::engine )
内容的提问来源于stack exchange,提问作者Akashdip Hazra
相关产品推荐
相关产品推荐

