第1.5章: 测试安装

English

创建一个简单的测试程序

在 第1.4章 安装好工具链后,你应当验证编译器能否正确工作。 使用你喜欢的任何文本编辑器——VS Code PWA、Vim、记事本或其他——创建一个名为 hello.cpp 的文件。

尽管本教程使用 fast_io 库而非 iostream, 传统的 C++ “Hello World” 程序仍然是测试安装的最简单方式:

#include <iostream>

int main()
{
    ::std::cout << "Hello World\n";
}

如果这个程序能够编译并运行,说明你的安装工作正常。

Clang 配置文件

第1.4章 的安装脚本会通过 create_cfgs.sh 或 create_cfgs.ps1 自动生成 Clang 配置文件。这些文件存放在:

Clang 的 .cfg 文件只是自动附加编译器选项而已。你可以用文本编辑器 打开它们,查看确切的编译选项。

1. 构建 Windows 二进制文件(交叉编译)

在除 macOS 之外的所有操作系统上,你都可以用 Clang 创建 Windows 二进制文件。 Wine(10 或更新版本)可以让你在 Linux、musl 或 Android 上运行这些二进制文件。

Linux / BSD / Android

clang++ -o hello.exe hello.cpp -O3 \
  --sysroot=$HOME/toolchains/windows-msvc-sysroot \
  -fuse-ld=lld -flto=thin \
  --target=x86_64-windows-msvc
wine ./hello.exe

如果你在 ARM 设备(Android、平板、VR 设备)上,请使用:

--target=aarch64-windows-msvc

Windows(CMD)

clang++ -o hello.exe hello.cpp -O3 ^
  --sysroot=%USERPROFILE%/toolchains/windows-msvc-sysroot ^
  -fuse-ld=lld ^
  --target=x86_64-windows-msvc
hello.exe

Windows(PowerShell)

clang++ -o hello.exe hello.cpp -O3 `
  --sysroot=$env:USERPROFILE/toolchains/windows-msvc-sysroot `
  -fuse-ld=lld -flto=thin `
  --target=x86_64-windows-msvc
./hello.exe

这些命令会产出一个链接到 Microsoft Visual C++ 运行时的 Windows 二进制文件。 Wine 提供了自己的实现,因此你无需在 Linux 上额外安装任何东西。

另一种链接方式示例

clang++ -o hello.exe hello.cpp -O3 \
  --sysroot=$HOME/toolchains/windows-msvc-sysroot \
  -fuse-ld=lld -D_DLL=1 -lmsvcrt
wine ./hello.exe

使用生成的 CFG 文件

clang++ -o hello.exe hello.cpp -O3 \
  --config=$HOME/cfgs/x86_64-windows-msvc.cfg
wine ./hello.exe

要为 ARM Windows 交叉编译:

clang++ -o hello.exe hello.cpp -O3 \
  --config=$HOME/cfgs/aarch64-windows-msvc.cfg

然后你可以把这个二进制文件拷贝到你的 ARM 设备(Android 等)上,用 Wine 运行它。

Windows 运行时说明

使用 Wine 运行 Clang 本身

第1.4章 中的脚本还会在 Linux 上安装一套 Windows Clang 工具链。你可以通过 Wine 调用它:

wine clang++ -o hello.exe hello.cpp -O3 \
  --config=$HOME/cfgs/aarch64-windows-msvc.cfg
wine ./hello.exe

2. 构建本地二进制文件

要确定你的平台目标三元组,请运行:

clang++ -v

macOS 上的示例输出:

Target: aarch64-apple-darwin24.4.0

重要的部分是三元组:aarch64-apple-darwin24。 llvm-releases 中的工具链包含许多常见三元组:

编译本地二进制文件

clang++ -o hello hello.cpp -O3 -flto=thin \
  --config=$HOME/cfgs/aarch64-apple-darwin24.cfg
./hello

在 macOS 上,这会产出一个通用二进制文件,同时包含 x86_64 和 aarch64 两部分, 因此它也能在 Intel Mac 和黑苹果系统上运行。

创建平台专属的二进制文件并不一定比通过 Wine 运行 Windows 二进制文件更“本地”。 Wine 是一个兼容层而不是模拟器,它可以避免 glibc 版本不匹配之类的问题。

3. 构建 WebAssembly 二进制文件

什么是字节码?

WebAssembly 是一种字节码格式——一套紧凑、平台无关的指令集。 字节码不与任何 CPU 架构绑定,而是由虚拟机或 JIT 编译器执行。

WebAssembly 与 Java 字节码的对比

换言之: Java 字节码是一种托管运行时格式。 WebAssembly 是一种可移植的、类似机器码的格式。

WAVM 不是工具链

WAVM 是一个WebAssembly 虚拟机,而不是编译器。 Clang 负责产出 WebAssembly 二进制文件,WAVM 只是运行它。

编译到 WebAssembly

clang++ -o hello hello.cpp -O3 -flto=thin \
  --config=$HOME/cfgs/wasm64-wasip1-noeh.cfg -s

用 WAVM 运行

wavm run --enable memtag --mount-root . ./hello

WebAssembly 内存标记基于作者的博士研究 (ACM CCSW 2025)。 它有助于检测内存安全缺陷,本教程后面会用到它。