如何使用CMake构建带有C++23标准库模块的项目(import std)?

Lee*_*awk 8 c++ cmake c++-modules c++23

众所周知,C++23 支持标准库模块。直到 2023 年 5 月,MSVC 都支持它,但我们需要像Microsoft 博客提到的那样手动添加标准库模块。

import std但是在CMake项目中如何使用呢?MS博客没有提到这一点。并且这些文件无法工作。(该std.ifc文件来自微软博客教程:(cl /std:c++latest /EHsc /nologo /W4 /MTd /c "%VCToolsInstallDir%\modules\std.ixx"在msvc x64本机控制台中使用))

CMakeList.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.26)

set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)

set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${CMAKE_PROJECT_NAME})


set(CMAKE_CXX_STANDARD 23)

project(1-1)

add_executable(${CMAKE_PROJECT_NAME})
target_sources(${CMAKE_PROJECT_NAME}
    PUBLIC
    FILE_SET all_my_modules TYPE CXX_MODULES FILES
    main.cpp
    std.ifc
)
Run Code Online (Sandbox Code Playgroud)

主程序

CMAKE_MINIMUM_REQUIRED(VERSION 3.26)

set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP ON)

set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${CMAKE_PROJECT_NAME})


set(CMAKE_CXX_STANDARD 23)

project(1-1)

add_executable(${CMAKE_PROJECT_NAME})
target_sources(${CMAKE_PROJECT_NAME}
    PUBLIC
    FILE_SET all_my_modules TYPE CXX_MODULES FILES
    main.cpp
    std.ifc
)
Run Code Online (Sandbox Code Playgroud)

MSVC 显示:

import std;
using namespace std;

int main(){
    cout<<"Hello\n";
}
Run Code Online (Sandbox Code Playgroud)

我可以使用复制%VCToolsInstallDir\modules\std.ixx到项目文件夹并更改std.ifcstd.ixx,但是有没有更优雅的方法来实现它以避免每次都构建 std 模块?我认为这是因为.ifc不是源文件,如何在CMake中处理它?

Com*_*sMS 7

请注意,Visual Studio 不断改变其工作方式,我将尝试随着事情的进展更新答案。

作为先决条件,您需要设置CMAKE_CXX_STANDARD为使用 C++23:

[...]
set(CMAKE_CXX_STANDARD 23)

add_executable(demo)
target_sources(demo
  PRIVATE
    demo.cpp
)
Run Code Online (Sandbox Code Playgroud)

这会将 VS 配置属性设置C/C++->Language->C++ Language Standard/std:c++latest。Visual Studio 17.6 现在还提供了一个属性,C/C++->Language->Build ISO C++23 Standard Library Modules该属性需要Yes并且随后将自动构建标准库模块/std:c++latest作为项目构建的一部分。

此选项过去默认情况下处于激活状态,但 Visual Studio 最近将该默认值更改为No,因此您现在需要手动激活该选项。CMake 目前正在考虑提供一个选项来控制此属性

对于旧版本的 Visual Studio,您必须在导入之前自行std编译命名模块。

由于 CMake 目前不支持导入预编译模块,因此运行最简单的方法就是在项目中包含标准库的主模块接口。

请务必首先阅读此答案,以了解 CMake 中 C++20 模块的当前先决条件和限制。

CMakeLists.txt

[...]
add_executable(demo)

file(COPY
  # you don't want to hardcode the path here in a real-world project,
  # but you get the idea
  "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.36.32532/modules/std.ixx"
  DESTINATION
  ${PROJECT_BINARY_DIR}/stdxx
)

target_sources(demo
  PRIVATE
  FILE_SET CXX_MODULES FILES
  ${PROJECT_BINARY_DIR}/stdxx/std.ixx
  PRIVATE
  demo.cpp
)
Run Code Online (Sandbox Code Playgroud)

演示.cpp

import std;

int main()
{
    std::cout << "Hello World\n";
}
Run Code Online (Sandbox Code Playgroud)

CMake 正确地阻止您在构建中包含源树之外的模块源。因此,我们将模块接口文件复制到我们的二叉树中进行构建。

像往常一样,不允许相同的主模块接口在程序中多次出现。相应地构建您的构建,这样您就不会意外地被std.ixx编译两次。