You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从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:

  1. 子项目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()
  1. 主项目引入子项目后添加:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:24:26