CMake目标未在add_subdirectory前导出,插件无法调用find_package问题
问题解答
1. add_subdirectory 和 export(EXPORT) 的执行顺序问题
不是优先级高低的问题,CMake是严格按脚本书写顺序执行的。如果你在主CMakeLists.txt里先写add_subdirectory(plugins)再写export(EXPORT),处理插件脚本时接口库的目标导出操作还没执行,插件的find_package自然找不到对应目标文件。
2. 如何在处理插件前导出目标
调整CMake脚本执行顺序即可,把接口库的定义、导出操作放在add_subdirectory(plugins)之前:
- 先完整定义接口库目标(包括设置头文件目录、编译选项等)
- 立即执行
export(EXPORT)命令,将接口库目标导出到构建树的CMake文件中 - 随后再调用
add_subdirectory(plugins)处理插件代码
另外,为让插件在构建树中找到导出目标,需配合export(PACKAGE <你的包名>)命令将包注册到CMake用户包注册表,或在插件构建时指定CMAKE_PREFIX_PATH包含主项目构建目录。
3. 让插件在构建树/安装树中通过find_package找到接口库
构建树场景
- 主项目中,接口库目标定义完成后执行
export(EXPORT)生成导出文件:
export(EXPORT MyInterfaceTargets FILE "${PROJECT_BINARY_DIR}/MyInterfaceTargets.cmake" )
- 编写配置文件模板(比如
MyInterfaceConfig.cmake.in):
@PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/MyInterfaceTargets.cmake") check_required_components(MyInterface)
- 用
configure_file生成构建树可用的配置文件,并注册包:
configure_file(MyInterfaceConfig.cmake.in "${PROJECT_BINARY_DIR}/MyInterfaceConfig.cmake" @ONLY ) export(PACKAGE MyInterface)
- 插件的CMakeLists.txt中直接使用
find_package(MyInterface REQUIRED)即可,CMake会通过注册表找到构建树中的配置文件。
安装树场景
- 主项目中,用
install(EXPORT)将目标导出文件安装到指定目录:
install(EXPORT MyInterfaceTargets FILE MyInterfaceTargets.cmake DESTINATION lib/cmake/MyInterface )
- 用
CMakePackageConfigHelpers模块生成版本文件和配置文件并安装:
include(CMakePackageConfigHelpers) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/MyInterfaceConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion ) install(FILES "${PROJECT_BINARY_DIR}/MyInterfaceConfig.cmake" "${PROJECT_BINARY_DIR}/MyInterfaceConfigVersion.cmake" DESTINATION lib/cmake/MyInterface )
- 同时安装接口库的头文件和目标:
install(TARGETS MyInterface EXPORT MyInterfaceTargets INCLUDES DESTINATION include ) install(DIRECTORY include/ DESTINATION include)
- 安装完成后,插件的
find_package(MyInterface REQUIRED)会自动在系统默认路径或CMAKE_PREFIX_PATH指定路径中找到接口库配置文件。
内容的提问来源于stack exchange,提问作者ManuelSchneid3r
相关产品推荐
相关产品推荐

