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

如何将已编译的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 05:30:19