如何将Vcpkg引入的依赖与CMake库一同打包并提供给其他项目?
解决Vcpkg依赖Eigen的CMake库被非Vcpkg项目消费时的依赖问题
问题根源分析
- Eigen的目标类型特殊性:Eigen是纯头文件库,
Eigen3::Eigen是CMake的INTERFACE目标,仅包含头文件路径,没有任何编译生成的二进制文件(.lib/.dll等)。这就是为什么你用install(IMPORTED_RUNTIME_ARTIFACTS)或$<TARGET_FILE:Eigen3::Eigen>会报错——这些命令仅适用于有二进制产物的目标。 - Vcpkg的依赖隔离:你的项目用Vcpkg管理Eigen时,Vcpkg会自己维护Eigen的配置文件路径,但非Vcpkg消费项目的
CMAKE_PREFIX_PATH不会包含Vcpkg的包目录,因此find_package(Eigen3)会失败。
解决方案
方案一:将Eigen头文件随你的库一起安装
把Eigen的头文件打包到你的库的安装目录中,让消费项目无需单独安装Eigen即可使用。
在你的项目CMakeLists.txt中添加以下代码:
# 找到Eigen后,获取其头文件目录 find_package(Eigen3 3.4 CONFIG REQUIRED NO_MODULE) get_target_property(EIGEN_INCLUDE_DIRS Eigen3::Eigen INTERFACE_INCLUDE_DIRECTORIES) # 安装Eigen的核心头文件到你的库的安装目录下的thirdparty子目录 install(DIRECTORY ${EIGEN_INCLUDE_DIRS}/Eigen DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/thirdparty FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp") # 更新你的目标的INTERFACE_INCLUDE_DIRECTORIES,让消费项目能找到安装后的Eigen target_include_directories(<my_target> INTERFACE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> # 添加Eigen的安装路径 $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/thirdparty> )
然后修改<my_target>-config.cmake,移除原有的find_package(Eigen3)调用——因为Eigen头文件已经随你的库一起安装,消费项目无需单独查找:
# 不再需要find_dependency(Eigen3) include(${CMAKE_CURRENT_LIST_DIR}/<my_target>-targets.cmake)
方案二:在config.cmake中添加依赖查找 fallback 逻辑
保留find_package的同时,添加 fallback 机制:如果消费项目找不到系统/Vcpkg的Eigen,就使用你预先安装的Eigen头文件(需要先按方案一安装Eigen头文件到你的库目录)。
修改<my_target>-config.cmake为:
include(CMakeFindDependencyMacro) # 先尝试查找系统或Vcpkg管理的Eigen,QUIET避免报错 find_dependency(Eigen3 3.4 CONFIG QUIET NO_MODULE) if(NOT Eigen3_FOUND) # 如果找不到,初始化一个本地的Eigen3::Eigen接口目标 set(EIGEN_LOCAL_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}/../include/thirdparty") if(NOT EXISTS ${EIGEN_LOCAL_INCLUDE_DIR}/Eigen) message(FATAL_ERROR "Eigen3 not found locally or in system. Ensure Eigen headers are installed with <my_target>.") endif() add_library(Eigen3::Eigen INTERFACE IMPORTED) target_include_directories(Eigen3::Eigen INTERFACE ${EIGEN_LOCAL_INCLUDE_DIR}) endif() include(${CMAKE_CURRENT_LIST_DIR}/<my_target>-targets.cmake)
关键注意事项
- 方案一适合希望完全隔离依赖的场景,消费项目无需关心Eigen的存在;
- 方案二兼容消费项目已安装Eigen的情况,优先使用系统/Vcpkg的版本,避免重复依赖;
- 无论哪种方案,都要确保安装的Eigen头文件版本与你的项目编译时使用的版本一致,避免兼容性问题。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

