Ch1.5: Test Installation
Create a Simple Test Program
After installing the toolchains in Ch1.4, you should verify that your compiler works correctly.
Use any text editor you prefer — VS Code PWA, Vim, Notepad, or others — and create a file named
hello.cpp.
Although this tutorial uses the fast_io library instead of iostream,
a traditional C++ “Hello World” program is still the simplest way to test your installation:
#include <iostream>
int main()
{
::std::cout << "Hello World\n";
}
If this program compiles and runs, your installation is functioning correctly.
Clang Configuration Files
The installation scripts from Ch1.4 automatically generate Clang configuration files using
create_cfgs.sh or create_cfgs.ps1. These files are stored in:
- Linux / macOS / Android:
$HOME/cfgs - Windows:
%USERPROFILE%/cfgs
A Clang .cfg file simply appends compiler flags automatically. You can open them in a text editor to inspect the exact compilation options.
1. Build a Windows Binary (Cross‑Compilation)
On all operating systems except macOS, you can create Windows binaries using Clang. Wine (version 10 or newer) allows you to run these binaries on Linux, musl, or 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
If you are on an ARM device (Android, tablets, VR devices), use:
--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
These commands produce a Windows binary linked against the Microsoft Visual C++ runtime. Wine provides its own implementation, so you do not need to install anything extra on Linux.
Alternative Linking Example
clang++ -o hello.exe hello.cpp -O3 \
--sysroot=$HOME/toolchains/windows-msvc-sysroot \
-fuse-ld=lld -D_DLL=1 -lmsvcrt
wine ./hello.exe
Using the Generated CFG Files
clang++ -o hello.exe hello.cpp -O3 \
--config=$HOME/cfgs/x86_64-windows-msvc.cfg
wine ./hello.exe
To cross‑compile for ARM Windows:
clang++ -o hello.exe hello.cpp -O3 \
--config=$HOME/cfgs/aarch64-windows-msvc.cfg
You can then copy the binary to your ARM device (Android, etc.) and run it with Wine.
Windows Runtime Notes
- Most Windows systems already include the MSVC runtime.
- If DLLs are missing, install the latest redistributable:
- Microsoft VC Redistributable
- Windows on ARM users should install x86, x64, and arm64 redistributables.
Using Wine to Run Clang Itself
The script in Ch1.4 also installs a Windows Clang toolchain on Linux. You can invoke it through Wine:
wine clang++ -o hello.exe hello.cpp -O3 \
--config=$HOME/cfgs/aarch64-windows-msvc.cfg
wine ./hello.exe
2. Build a Native Binary
To determine your platform’s target triple, run:
clang++ -v
Example output on macOS:
Target: aarch64-apple-darwin24.4.0
The important part is the triplet: aarch64-apple-darwin24.
The toolchains from llvm-releases include many common triplets:
- aarch64-apple-darwin24
- aarch64-linux-android30
- aarch64-windows-gnu
- x86_64-linux-gnu
- x86_64-windows-gnu
- wasm64-wasip1
Compile a Native Binary
clang++ -o hello hello.cpp -O3 -flto=thin \
--config=$HOME/cfgs/aarch64-apple-darwin24.cfg
./hello
On macOS, this produces a universal binary containing both x86_64 and aarch64 slices, so it also runs on Intel Macs and Hackintosh systems.
Creating a platform‑specific binary does not necessarily make it more “native” than running a Windows binary through Wine. Wine is a compatibility layer, not an emulator, and avoids issues like glibc version mismatches.
3. Build a WebAssembly Binary
What Is Bytecode?
WebAssembly is a bytecode format — a compact, platform‑independent instruction set. Bytecode is not tied to any CPU architecture. Instead, it is executed by a virtual machine or JIT compiler.
How WebAssembly Compares to Java Bytecode
- Java bytecode runs on the JVM, which provides garbage collection, threads, exceptions, and a large runtime.
- WebAssembly bytecode is much lower‑level and closer to native machine code.
- WASM does not include garbage collection, threads (unless WASM threads are enabled), or exceptions.
- WASM is designed for portability and sandboxing, not for running Java‑style managed languages.
In other words: Java bytecode is a managed runtime format. WebAssembly is a portable machine‑code‑like format.
WAVM Is Not a Toolchain
WAVM is a WebAssembly virtual machine, not a compiler. Clang produces the WebAssembly binary. WAVM simply runs it.
Compile to WebAssembly
clang++ -o hello hello.cpp -O3 -flto=thin \
--config=$HOME/cfgs/wasm64-wasip1-noeh.cfg -s
Run with WAVM
wavm run --enable memtag --mount-root . ./hello
WebAssembly Memory Tagging is based on the author’s Ph.D. research (ACM CCSW 2025). It helps detect memory safety bugs and will be used later in this tutorial.