如何将已编译的C++20模块复用至另一项目?
问题描述
目标是将项目中生成的C++20模块复用至另一个项目,此前测试GitHub仓库方案可正常使用模块,但自行操作时遇到问题。
生成模块的第一个项目
已修改CMake结构如下:
cmake_minimum_required(VERSION 3.26) set(APP_NAME CppModules) project(${APP_NAME} LANGUAGES CXX) set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a") set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_EXTENSIONS Off) add_executable(${APP_NAME} main.cpp) add_library(my_lib2) target_sources(my_lib2 PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES src/my_lib/my_lib2.cpp ) add_library(my_lib) target_sources(my_lib PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES src/my_lib/my_lib.cpp ) target_link_libraries(${APP_NAME} PRIVATE my_lib my_lib2 ) set_target_properties(${APP_NAME} PROPERTIES LINKER_LANGUAGE CXX)
已生成若干.pcm文件以及my_lib.a、my_lib2.a文件。
导入模块的第二个项目
代码结构:
import my_lib; int main() { foo f; f.helloworld(); return 0; }
编译时报错:
fatal error: module 'my_lib' not found
使用的CMake配置:
cmake_minimum_required(VERSION 3.26) set(APP_NAME Importer) project(${APP_NAME} LANGUAGES CXX) set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a") set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_EXTENSIONS Off) add_executable(${APP_NAME} main.cpp) target_link_libraries(${APP_NAME} PRIVATE /absolute/path/to/libmy_lib.a) set_target_properties(${APP_NAME} PROPERTIES LINKER_LANGUAGE CXX)
询问:缺失的操作步骤是什么?如何将已生成的模块注入到第二个项目?
解决方案
问题核心是仅链接静态库不足以让CMake和编译器识别C++模块,还需传递模块接口文件(.pcm)的路径及相关编译配置。以下是完整解决步骤:
步骤1:在第一个项目中导出模块的CMake配置
修改第一个项目的CMakeLists.txt,添加安装/导出逻辑,让CMake生成可被其他项目导入的模块配置文件:
# 在第一个项目的CMakeLists.txt末尾添加 install(TARGETS my_lib my_lib2 EXPORT MyLibTargets FILE_SET cxx_modules DESTINATION lib/cmake/my_lib LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) install(EXPORT MyLibTargets FILE MyLibTargets.cmake DESTINATION lib/cmake/my_lib ) # 生成版本和配置文件 include(CMakePackageConfigHelpers) write_basic_package_version_file( "MyLibConfigVersion.cmake" VERSION 1.0.0 COMPATIBILITY SameMajorVersion ) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/MyLibConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake" INSTALL_DESTINATION lib/cmake/my_lib ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/MyLibConfigVersion.cmake" DESTINATION lib/cmake/my_lib )
同时在第一个项目根目录创建MyLibConfig.cmake.in文件,内容为:
@PACKAGE_INIT@ include("${CMAKE_CURRENT_LIST_DIR}/MyLibTargets.cmake") check_required_components(my_lib)
执行安装命令,将模块安装到指定目录:
cd 第一个项目的build目录 cmake --install . --prefix /自定义的安装路径
步骤2:在第二个项目中导入模块配置
修改第二个项目的CMakeLists.txt,通过CMake的find_package导入第一个项目的模块配置:
cmake_minimum_required(VERSION 3.26) set(APP_NAME Importer) project(${APP_NAME} LANGUAGES CXX) set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a") set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_EXTENSIONS Off) # 指定第一个项目的安装目录,让CMake找到模块配置文件 set(MyLib_DIR "/自定义的安装路径/lib/cmake/my_lib") find_package(MyLib REQUIRED) add_executable(${APP_NAME} main.cpp) # 链接导入的模块目标,CMake会自动处理.pcm文件和编译依赖 target_link_libraries(${APP_NAME} PRIVATE my_lib) set_target_properties(${APP_NAME} PROPERTIES LINKER_LANGUAGE CXX)
替代方案:直接导入第一个项目的构建目录
如果不想执行安装步骤,可在第二个项目中直接导入第一个项目的构建产物:
# 在第二个项目的CMakeLists.txt中添加 add_subdirectory(/第一个项目的build目录 my_lib_build) # 或者使用find_package指向构建目录 set(MyLib_DIR "/第一个项目的build目录") find_package(MyLib REQUIRED)
CMake会自动识别模块的.pcm文件路径及相关配置,无需手动指定。
关键说明
C++模块的复用不是仅链接静态库就能完成的——编译器需要找到对应的.pcm模块接口文件,CMake通过FILE_SET cxx_modules和导出/导入机制,自动传递这些路径和编译选项。仅手动链接.a文件无法让编译器知晓模块的存在,这就是报错的核心原因。
内容的提问来源于stack exchange,提问作者Kroma
相关产品推荐
相关产品推荐

