第1.8章: fast_io

English

使用 fast_io(仅头文件)

在 第1.5章 中,我们克隆了 fast_io 仓库。 fast_io 是一个仅头文件的库,因此你不需要构建任何东西。 你只需把 include 目录加入编译器选项。

假设你把 fast_io 克隆到了:

$HOME/libraries/fast_io

那么你可以在程序中包含它:


#include <fast_io.h>

int main() {
    print("Hello from fast_io!\n");
}

并通过添加以下选项来编译:

-I$HOME/libraries/fast_io/include

这会告诉编译器到哪里去找 fast_io.h。

两个必需的选项:-fherbceptions -lherbceptions

fast_io 把每一个错误都报告为 赫布异常, 而赫布异常是一项编译器特性。所以仅靠 include 目录是不够的:你还需要 赫布异常运行时,以及一个实现了该语言特性的编译器。

只有我们的 GCC 和 LLVM 构建支持赫布异常。原版编译器 和 MSVC 则不支持——没有办法用 cl.exe 编译 fast_io。 完整解释以及每一条错误报告规则见 第3.16章: 赫布异常。

不需要别的东西:赫布异常的头文件与库都是你所安装工具链的一部分, 所以 -lherbceptions 就是全部额外的添加。假设 fast_io 被克隆到 $HOME/libraries/fast_io:


FASTIO=$HOME/libraries/fast_io

用 Clang 编译

示例:使用 Clang 和 MSVC sysroot 构建一个 Windows MSVC 二进制文件:


clang++ --config=$HOME/cfgs/x86_64-windows-msvc.cfg \
  -O3 -flto=thin -fherbceptions \
  -I$FASTIO/include \
  hello.cpp -lherbceptions -o hello.exe

赫布异常运行时位于 sysroot 中: 链接时是 lib/<triple>/herbceptions.lib, 运行时是 bin/<triple>/herbceptions.dll(Wine 通过 WINEPATH 找到它)。我们的 MinGW g++ 用自己的导入库 复用同一个 DLL,并且需要 -lntdll,因为 fast_io 直接与 NT 打交道:


x86_64-w64-mingw32-g++ -o hello.exe hello.cpp \
  -std=c++26 -O3 -s \
  -fherbceptions \
  -I$FASTIO/include \
  -lherbceptions -lntdll

wine ./hello.exe

要查看一个 Windows 二进制文件需要哪些 DLL,请使用 win-ldd:


wine $HOME/softwares/win-ldd/x86_64-windows-msvc/win-ldd.exe ./hello.exe
关于这些选项的说明:MSVC sysroot 已经自带 Windows 的赫布异常运行时(链接用 herbceptions.lib, 运行时用 herbceptions.dll),所以 --sysroot 就能找到它, 永远不需要写 -L。GCC/GNU 目标的构建还会额外传入 -s 来剥离二进制文件。

用 GCC 编译

GCC 的工作方式相同,前提是使用我们带赫布异常的 GCC 构建:


g++ -o hello hello.cpp \
  -std=c++26 -O3 -s -fuse-ld=lld \
  -fherbceptions \
  -I$FASTIO/include \
  -lherbceptions

不支持 MSVC(cl.exe)

对 fast_io 而言,MSVC 不是受支持的编译器。它没有 -fherbceptions,而 fast_io 通过赫布异常通道报告每一个错误, 因此本教程的错误契约无法用它表达。请使用我们的 GCC 或 LLVM 分支。

在 Windows 上,请使用我们面向 x86_64-windows-msvc 的 Clang(就是 上面那条命令——它产出一个普通的 Windows 二进制文件,用 lld 链接),或者我们的 MinGW GCC。cl.exe 和 Visual Studio 的 常规 C++ 工具集都不参与其中。

使用 fast_io 模块

fast_io 也提供 C++20 模块文件。 它们位于:

{fast_io_cloned_dir}/share/fast_io

示例目录:


/Users/username/libraries/fast_io/share/fast_io

内容:


fast_io.cppm
fast_io_crypto.cppm
fast_io_legacy.cppm
fast_io_inc/

如何导入模块

创建一个文件 hello.cpp:


import fast_io;

int main() {
    using namespace ::fast_io::io;
    print("Hello from fast_io module!\n");
}

用 Clang 编译 fast_io 模块

首先,编译模块接口:


clang++ --config=$HOME/cfgs/x86_64-linux-gnu-libcxx.cfg \
  -O2 -fherbceptions -I$FASTIO/include \
  -x c++-module $FASTIO/share/fast_io/fast_io_json.cppm \
  -o fast_io.json.pcm --precompile

然后用该 PCM 编译你的程序:


clang++ --config=$HOME/cfgs/x86_64-linux-gnu-libcxx.cfg \
  -O2 -fherbceptions -I$FASTIO/include \
  -fmodule-file=fast_io.json=fast_io.json.pcm \
  hello.cpp fast_io.json.pcm -lherbceptions \
  -o hello

模块只需预编译一次,之后即可导入;导入处除了 #include <herbceptions/error>(当你想自己编写 catch throws 处理程序时)之外,不需要头文件里的任何东西。

关于模块文件名的状态: fast_io_json.cppm 目前可以干净地预编译并导入,也是本示例所用的那个。 总括式的 fast_io.cppm 仍在追赶头文件,所以如果预编译它在失败, 请改用头文件接口(#include <fast_io.h>)——本教程其余部分 用的就是这个。

用 GCC 编译 fast_io 模块

GCC 的模块支持仍是实验性的,而且我们带赫布异常的 GCC 构建 在某些 fast_io 模块单元上已知会崩溃(ICE)——请用 Clang 编译 这组模块,或者用 GCC 时改用头文件接口。


g++ -std=c++26 -fmodules -fherbceptions -O3 -s -fuse-ld=lld \
  -c $FASTIO/share/fast_io/fast_io_json.cppm \
  -I$FASTIO/include \
  -o fast_io.json.gcm

g++ -std=c++26 -fmodules -fherbceptions -O3 -s -fuse-ld=lld hello.cpp \
  fast_io.json.gcm \
  -I$FASTIO/include \
  -lherbceptions \
  -o hello

MSVC 无法编译该模块

MSVC 不是 fast_io 支持的编译器:它没有赫布异常,而库中的每个错误 都被报告为赫布异常。我们的 GCC 和 LLVM 分支是本教程唯一支持的编译器。 Windows 二进制文件是用我们面向 MSVC ABI 的 Clang(或我们的 MinGW GCC)构建的—— 产出的可执行文件是普通的 Windows 二进制文件,只不过不是由 cl.exe 生成的而已。

要点