02 — Compilers and Toolchains¶
You install both gcc and clang, and you build against both regularly. Not because you’re indecisive, but because catching bugs is a numbers game: gcc’s warnings sometimes catch what clang’s don’t, and vice versa. -fsanitize= on clang is often ahead of gcc’s implementation. Cross-compiler discipline is what separates hobbyist C from professional C.
GCC 15 (mid-2026 stable)¶
Current stable: GCC 15.2 (released Aug 8 2025). GCC 15.1 released April/May 2025. GCC 16 is under development; do not chase it.
What’s new that affects you:
Default C standard is now
gnu23. If you want strict portable C, pass-std=c17or-std=c23explicitly.Full C23 language support including
_BitInt,#embed, improvedtypeof,constexprat file scope.AVX10.2 codegen (relevant for Intel Xeon deployments).
Improved OpenMP 6.0 support.
Incremental LTO — much less painful
-fltobuilds.COBOL front-end (
gcobol) — irrelevant to you; skip.
Install:
macOS:
brew install gcc— installs asgcc-15(notgcc).Ubuntu 26.04:
sudo apt install gcc g++— GCC 15 is default.WSL2 Ubuntu 26.04: same.
Verify: gcc-15 --version (Mac) or gcc --version (Linux) → shows 15.2.0 or newer.
Clang / LLVM 20 (mid-2026 stable)¶
Current stable: LLVM/Clang 20.1 (first stable of the 20 series, released March 2025). Clang 21 discussed at Oct 2025 LLVM devmtg; expect it late 2025/early 2026 — use if you like, 20.1 is fine.
Why you also want clang:
Sanitizer implementations often lead gcc’s.
Better error messages (still).
clang-tidy,clang-format,scan-buildare part of the same toolchain.clangd(see file 03) is the LSP for C.
Install:
macOS:
xcode-select --install(bundled clang). For latest,brew install llvmand put/opt/homebrew/opt/llvm/binonPATH.Ubuntu:
sudo apt install clang lldb clang-tools clang-tidy clang-format clangd.
Verify: clang --version.
The two-compiler discipline¶
Always build once with each in CI (even in your personal projects). Simple pattern in a Makefile:
CC ?= gcc
CFLAGS = -std=c17 -Wall -Wextra -Wpedantic -O2 -g
all: prog
prog: main.c
$(CC) $(CFLAGS) -o $@ $<
check:
CC=gcc $(MAKE) prog
CC=clang $(MAKE) prog
./prog
CC=clang CFLAGS="$(CFLAGS) -fsanitize=address,undefined" $(MAKE) prog
./prog
ccache — install unconditionally¶
What: compiler cache; hashes preprocessed source, caches object files. Makes rebuilds 5-20x faster.
Install: brew install ccache / apt install ccache.
Setup: add to ~/.zshrc or ~/.bashrc:
export PATH="/opt/homebrew/opt/ccache/libexec:$PATH" # Mac
export PATH="/usr/lib/ccache:$PATH" # Ubuntu
export CCACHE_DIR="$HOME/.ccache"
export CCACHE_MAXSIZE="5G"
Verify: ccache -s shows stats after your next build.
Linkers — mold vs default ld/lld/gold¶
mold (rui314/mold, https://github.com/rui314/mold) is a modern parallel linker written by the same author as lld and gold. In benchmarks it is 5-25x faster than lld/gold for large C/C++ links.
Linker |
Platform |
Notes |
|---|---|---|
mold |
Linux (primary), FreeBSD, macOS (sold, alpha) |
Best choice on Linux |
lld |
All |
LLVM’s linker, second-best |
gold |
Linux |
Being deprecated |
BFD ld (default |
All |
Slowest, most portable |
ld64 (Apple) |
macOS |
The macOS system linker; still the right default on Mac. |
Install mold on Ubuntu 26.04: sudo apt install mold.
Use with GCC 12.1+ or Clang:
gcc -fuse-ld=mold -o prog main.c
Verify: mold --version. Measure your before/after link time on a real project.
Which compiler for what¶
Learning / canonical builds: gcc 15 with
-std=c17 -Wall -Wextra -Wpedantic -O2 -g.Sanitizer runs: clang 20 with
-fsanitize=address,undefined,integer(clang’s sanitizer set is broader than gcc’s).Comparing codegen: godbolt.org (Compiler Explorer) with both, side by side.
CI: both, always. If your code compiles cleanly on both with
-Werror, you have caught most portability bugs.
What most people get wrong about compilers¶
They install one, forget about it, and don’t turn on warnings. Then they wonder why they have subtle bugs. Minimum warning flags for every project, day one:
-Wall -Wextra -Wpedantic -Wshadow -Wstrict-prototypes -Wmissing-prototypes -Wconversion -Wdouble-promotion -Werror
Start there. Add -Wanalyzer-* on gcc for the static analyzer, -fsanitize=address,undefined for runtime.
Return to README.md · Next: 03_editor_and_lsp.md