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

如何生成C++20模块接口及可被外部项目引用的库包?

问题描述

我希望使用C++20模块创建一个基础库,并在外部简单项目中导入它,重点关注基于模块的库的输出包。

根据CPPCon相关演讲的结论,最佳方案是创建模块接口文件以及.lib或.dll这类二进制库。我当前使用的基础CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.28)

project(MyLib LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS NO)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

add_library(foo)
target_sources(foo
  PUBLIC
    FILE_SET CXX_MODULES FILES
      foo.cppm) 

foo.cppm的内容如下:

module;
#include <iostream>

export module foo;

export class foo {
public:
  foo() = default;
  ~foo() = default;
  void helloworld();
};

void foo::helloworld() { std::cout << "hello world\n"; }

目前构建后仅得到.lib文件作为输出。请问如何生成模块接口,以及如何制作可被消费项目使用的合格包?

假设消费项目使用完全相同的开发环境(CMake 3.28、MSVC 17.9.3),无需考虑二进制兼容性问题。


解决方案

1. 模块接口文件的生成与定位

MSVC下C++20模块的接口文件是.ifc格式,CMake在构建模块时已经自动生成了该文件,默认存放在构建目录的中间文件路径中(比如build/Debug/foo.dir/下)。你需要通过CMake的安装规则将其导出到指定位置,方便消费项目访问。

2. 调整CMake配置以生成可消费的包

修改库的CMakeLists.txt,添加安装规则、导出配置,让CMake生成消费项目所需的模块接口、二进制库和配置文件:

cmake_minimum_required(VERSION 3.28)

project(MyLib LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS NO)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

add_library(foo)
target_sources(foo
  PUBLIC
    FILE_SET CXX_MODULES FILES
      foo.cppm) 

# 设置安装目录,可根据需求调整
set(INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/install")
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR}")

# 安装库的二进制文件和模块接口
install(TARGETS foo
  EXPORT fooTargets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  FILE_SET CXX_MODULES DESTINATION cmake/modules)

# 导出目标配置文件
install(EXPORT fooTargets
  FILE fooTargets.cmake
  NAMESPACE MyLib::
  DESTINATION cmake)

# 生成包配置文件,方便消费项目用find_package导入
include(CMakePackageConfigHelpers)
configure_package_config_file(
  "${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in"
  "${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmake"
  INSTALL_DESTINATION cmake)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/fooConfig.cmake"
  DESTINATION cmake)

需要在库的源码目录下创建Config.cmake.in文件,内容如下:

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/fooTargets.cmake")
check_required_components(foo)

3. 构建并安装库

执行以下命令完成构建和安装:

cmake -S . -B build
cmake --build build --config Debug
cmake --install build --config Debug

安装完成后,install目录下会有:

  • lib/foo.lib:静态库文件
  • cmake/modules/foo.ifc:模块接口文件
  • cmake/fooConfig.cmake、cmake/fooTargets.cmake:CMake配置文件

4. 消费项目的配置

在外部消费项目的CMakeLists.txt中,通过find_package导入库并使用模块:

cmake_minimum_required(VERSION 3.28)

project(ConsumerProject LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS NO)
set(CMAKE_CXX_STANDARD_REQUIRED YES)

# 指定库的安装目录路径
set(MyLib_DIR "/path/to/MyLib/install/cmake")
find_package(MyLib REQUIRED)

add_executable(consumer main.cpp)
target_link_libraries(consumer PRIVATE MyLib::foo)

消费项目的main.cpp中直接导入模块使用:

import foo;

int main() {
  foo f;
  f.helloworld();
  return 0;
}

5. 打包成可分发的包

如果需要生成可分发的安装包,可以使用CMake的CPack功能,在库的CMakeLists.txt末尾添加:

include(CPack)

然后执行:

cmake --build build --target package

会生成如MyLib-1.0.0-win64.zip之类的压缩包,包含所有必要的文件。


内容的提问来源于stack exchange,提问作者Erwan Douaille

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 22:08:32