第1.5章: 测试安装
创建一个简单的测试程序
在 第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 配置文件。这些文件存放在:
- Linux / macOS / Android:
$HOME/cfgs - Windows:
%USERPROFILE%/cfgs
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 运行时说明
- 大多数 Windows 系统已经包含 MSVC 运行时。
- 如果缺少 DLL,请安装最新的可再发行组件:
- Microsoft VC Redistributable
- Windows on ARM 用户应安装 x86、x64 和 arm64 三个可再发行组件。
使用 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 中的工具链包含许多常见三元组:
- aarch64-apple-darwin24
- aarch64-linux-android30
- aarch64-windows-gnu
- x86_64-linux-gnu
- x86_64-windows-gnu
- wasm64-wasip1
编译本地二进制文件
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 字节码运行在 JVM 上,JVM 提供垃圾回收、线程、异常以及庞大的运行时。
- WebAssembly 字节码的层次低得多,更接近原生机器码。
- WASM 不包含垃圾回收、线程(除非启用 WASM 线程)或异常。
- WASM 是为可移植性与沙箱化而设计的,而不是为了运行 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)。 它有助于检测内存安全缺陷,本教程后面会用到它。