C++23新特性:标准库模块(一)
Preface
随着LLVM 19 release的发布,标准模板库STL终于可以使用import
关键字进行导入了。这一特性本该随着C++20 Modules特性的落地而落地,但是由于编译器御三家的进展缓慢而拖到了今天。
值得注意的是,即便目前MSVC/LLVM已经完全支持[1]了STL modules,但是它的大规模应用仍然有种遥不可及的味道。目前C++构建系统的事实标准,cmake对modules的支持仍有限:
- 仅支持Ninja/MSVC构建
- 不支持STL modules或者其他由编译器提供的modules
此外,C++构建系统的后起之秀xmake,实现了较好的modules支持,供参考:xmake: C++20 modules。
工具方面,LLVM附带的一些C++ tools对STL modules的支持可以说比较完善:语言服务器clangd支持从std
模块中补全、查看以及重构;格式化工具clang-format
也可以对import
语句进行处理;静态检查工具clang-tidy
在某些情况下会出现错误,但是大部分情况是可以运行的。
本文主要介绍如何初步使用STL modules,以及clangd
工具的配置。
Getting Started
Source Code
本文使用单文件进行测试,代码如下。
// main.cpp |
Compiling with STL Modules Step by Step
测试环境:
- LLVM 19.1.5 (aarch64), installed by Homebrew.
- Visual Studio Code
Step 0. Generate the Built Module Interface (BMI, .pcm
Files)
LLVM 19虽然完整实现了STL modules,但是并没有提供预编译好的BMI文件。因此在使用import std;
之前,必须先编译STL modules:
clang++ -std=c++23 \ |
这条命令将会在当前目录下生成std.pcm
文件,供main.cpp
使用。注意std.cppm
文件位置即可。
Step 1. Compile the main.cpp
使用这条命令编译main.cpp
:
clang++ -std=c++23 main.cpp -o main -fmodule-file=std=std.pcm -fprebuilt-module-path=. |
其中,-fmodule-file=<module-name>=<BMI-file>
指定了导入的模块名,以及BMI文件名,-fprebuilt-module-path
指定了BMI文件的搜索路径。
如果编译成功,则可以运行./main
查看结果。
Step 2. Configure the LSP Server clangd
本文通过vscode调用clangd
。
通过vscode-clangd插件传递给clangd
的命令行参数如下:
{ |
需要注意的是,--experimental-modules-support
必须存在,否则clangd
可能无法识别import
关键字;此外--header-insertion
的值最好设置为never
,避免头文件自动插入导致clangd
解析失败。
除此之外,项目配置文件.clangd
必须存在,且-std=c++23
选项必须存在,不然clangd
可能会无法识别STL modules。
--- # .clangd |
除此之外,后续-f
选项也是必须的:-fbuiltin-module-map
为clangd
提供了STL modules的内容信息,缺少此项会导致clangd
可以识别到std
是有效的模块,但是无法生成相关的补全建议,也无法通过hover hints查看STL类和函数的相关信息;后两者在上一步中已经提到过,此处不再赘述。
优势与缺点
Modules无疑是便利的,仅以STL而言,几乎所有的#include
都可以被一条import
语句所替换。而且由于预编译模块的存在,编译时长必然存在明显的下降,这对大型项目而言无疑是重大利好。
但是目前由于Modules自身的限制(不能导出宏定义等),以及构建系统的支持问题,使用它替代传统头文件,或者说预处理器的路还很漫长。
工具方面,clangd
作为目前唯二的C++ LSP server之一[2],它必须依赖module map才可以查找模块的内容并提供相关信息,而LLVM目前还不能根据模块的编译信息自动生成module map备用,这导致clangd
的使用也受到了一定的限制。相关讨论见clangd discussion #1979。而且目前它还存在一些其他的bug,例如无法为import
关键字正确提供基于语义的高亮。
总的来说,STL modules还不太能满足笔者的期望,期待它的后续发展。
References
- P2465R3: Standard Library Modules
std
andstd.compat
- LLVM doc: Standard C++ Modules
- Modules Report for C++20