如何从CMake子目录传递CMAKE_MODULE_PATH变量至主项目
问题描述
我有两个项目,主项目将子项目作为子目录引入。子项目中我给CMAKE_MODULE_PATH添加了自身CMake模块的路径,但主项目通过add_subdirectory命令引入子项目后,在主项目里尝试引入子项目的CMake模块时,出现以下错误:
CMake Error at tests/CMakeLists.txt:7 (include):
include could not find requested file
此时检查发现CMAKE_MODULE_PATH是空的。请问如何保留子项目中CMAKE_MODULE_PATH的值,以便在主项目中使用?
子项目CMakeLists.txt代码
cmake_minimum_required(VERSION 3.23 FATAL_ERROR) set(UTILS_PROJECT_NAME "utils") set(UTILS_LIB_NAME "utils") set(UTILS_VERSION_MAJOR 0) set(UTILS_VERSION_MINOR 0) set(UTILS_VERSION_PATCH 1) set(UTILS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) if(${CMAKE_SOURCE_DIR} STREQUAL ${UTILS_SOURCE_DIR}) set(UTILS_STANDALONE ON) message(STATUS "utils standalone") endif() option(UTILS_BUILD_DOCS "Build the utils documentation" OFF) option(UTILS_BUILD_TESTS "Guild the utils tests and examples" ${UTILS_STANDALONE}) project(${UTILS_PROJECT_NAME} VERSION ${UTILS_VERSION_MAJOR}.${UTILS_VERSION_MINOR}.${UTILS_VERSION_PATCH} LANGUAGES CXX ) ... setup library target ... if(NOT "${UTILS_SOURCE_DIR}/cmake" IN_LIST CMAKE_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH "${UTILS_SOURCE_DIR}/cmake") endif() if (${UTILS_BUILD_DOCS}) add_subdirectory(docs) endif() if(${UTILS_BUILD_TESTS}) add_subdirectory(tests) endif()
主项目CMakeLists.txt代码
cmake_minimum_required(VERSION 3.23 FATAL_ERROR) set(ENGINE_PROJECT_NAME "engine") set(ENGINE_LIB_NAME "engine") set(ENGINE_VERSION_MAJOR 0) set(ENGINE_VERSION_MINOR 0) set(ENGINE_VERSION_PATCH 1) set(ENGINE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) if(${CMAKE_SOURCE_DIR} STREQUAL ${ENGINE_SOURCE_DIR}) set(ENGINE_STANDALONE ON) message(STATUS "engine standalone") endif() option(ENGINE_BUILD_TESTS "Build the tests and examples" ${ENGINE_STANDALONE}) project(${ENGINE_PROJECT_NAME} VERSION ${ENGINE_VERSION_MAJOR}.${ENGINE_VERSION_MINOR}.${ENGINE_VERSION_PATCH} LANGUAGES CXX ) # bad way list(APPEND CMAKE_MODULE_PATH "${ENGINE_SOURCE_DIR}/src/ext/utils/cmake") add_subdirectory(src) # add_subdirectory(path/to/utils) if(${ENGINE_BUILD_TESTS}) add_subdirectory(tests) # use utils cmake modules (utils_add_tests) endif()
解决方案
方法1:子项目同步修改到父作用域
CMake中list(APPEND)默认仅在当前作用域生效,子项目对CMAKE_MODULE_PATH的修改不会自动传递给主项目。可以在子项目添加模块路径时,将修改同步到父作用域:
修改子项目中的对应代码:
if(NOT "${UTILS_SOURCE_DIR}/cmake" IN_LIST CMAKE_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH "${UTILS_SOURCE_DIR}/cmake") # 把修改同步到主项目的作用域 set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE) endif()
方法2:子项目暴露专用模块路径变量(更规范)
子项目定义独立变量存储自身模块路径,再导出到父作用域,主项目按需添加到自己的CMAKE_MODULE_PATH:
- 子项目CMakeLists.txt中添加:
# 定义变量存储自身模块路径,标记为内部缓存变量 set(UTILS_CMAKE_MODULE_PATH "${UTILS_SOURCE_DIR}/cmake" CACHE INTERNAL "Path to utils CMake modules") # 子项目自身使用时,先加到自己的CMAKE_MODULE_PATH if(NOT "${UTILS_CMAKE_MODULE_PATH}" IN_LIST CMAKE_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH "${UTILS_CMAKE_MODULE_PATH}") endif()
- 主项目引入子项目后添加:
add_subdirectory(src/ext/utils) # 确保子项目路径正确 # 将子项目的模块路径加入主项目的CMAKE_MODULE_PATH if(NOT "${UTILS_CMAKE_MODULE_PATH}" IN_LIST CMAKE_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH "${UTILS_CMAKE_MODULE_PATH}") endif()
方法3:主项目引入子项目后手动添加路径
如果无法修改子项目代码,主项目可以在引入子项目后,利用子项目定义的UTILS_SOURCE_DIR变量添加路径,避免硬编码:
add_subdirectory(src/ext/utils) if(NOT "${UTILS_SOURCE_DIR}/cmake" IN_LIST CMAKE_MODULE_PATH) list(APPEND CMAKE_MODULE_PATH "${UTILS_SOURCE_DIR}/cmake") endif()
以上三种方法都能让主项目的CMAKE_MODULE_PATH包含子项目的模块路径,解决找不到模块的问题。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

