Step 1 — Verify Xcode Command Line Tools

Goal

Confirm Apple's C++ toolchain is installed and discoverable. This gives us clang++, make, system headers, git, and lldb — everything needed for Phases 1–4.

Why This Step Exists

Apple ships a C/C++ toolchain as part of "Xcode Command Line Tools" (CLT) — a minimal subset of full Xcode. Almost every macOS development workflow starts here. Without it, even git is missing.

The CLT also installs the macOS SDK (the sysroot containing system headers like <stdio.h> and frameworks like Foundation). When clang compiles, it implicitly looks here.

Check What's Installed

# Where is the CLT installed?
xcode-select -p

# Expected (one of):
#   /Library/Developer/CommandLineTools                  ← CLT-only install
#   /Applications/Xcode.app/Contents/Developer            ← full Xcode install

If you see "No developer tools were found" or similar, install:

xcode-select --install

This opens a GUI dialog. Click "Install". Wait ~5 minutes.

Verify The Compiler

clang++ --version

Expected:

Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: arm64-apple-darwin24.0.0
Thread model: posix
InstalledDir: /usr/bin

Three things to notice in the output, each a teaching moment:

  1. "Apple clang" — this is Apple's fork, not upstream LLVM. The version number ("16.0.0") tracks Xcode releases, not LLVM major releases. (Apple Clang 16 ≈ LLVM 17 under the hood.)
  2. Target: arm64-apple-darwin24.0.0 — this is your default target triple. arm64 is the instruction set (Apple Silicon), apple is the vendor, darwin24 is the kernel version (macOS 15 = Darwin 24). The triple is what every LLVM backend uses to know what code to emit.
  3. InstalledDir: /usr/bin — Apple installs into /usr/bin, which is on your PATH by default. Compare with Homebrew LLVM in Step 3, which installs elsewhere.

See The SDK Location

xcrun --show-sdk-path

Expected (something like):

/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk

This is your sysroot — Clang's -isysroot default. Inside it:

ls "$(xcrun --show-sdk-path)/usr/include" | head
# stdio.h, stdlib.h, string.h, ...

ls "$(xcrun --show-sdk-path)/System/Library/Frameworks" | head
# Foundation.framework, AppKit.framework, ...

This is where #include <stdio.h> actually resolves. Without the SDK, the compiler doesn't know where the system headers live.

Quick Sanity Test

cat > /tmp/hello.cpp <<'EOF'
#include <cstdio>
int main() { std::puts("hello from " __VERSION__); return 0; }
EOF

clang++ -std=c++17 /tmp/hello.cpp -o /tmp/hello && /tmp/hello

Expected (something like):

hello from 4.2.1 Compatible Apple LLVM 16.0.0 (clang-1600.0.26.6)

If this works, your Apple Clang installation is healthy.

What Just Happened

  1. xcode-select -p confirmed the CLT prefix.
  2. clang++ --version printed the version, the default target triple (which equals your machine's host triple), and the install path.
  3. xcrun --show-sdk-path revealed your sysroot — the directory tree that the compiler treats as the target's / when looking for headers and frameworks.
  4. Compiling hello.cpp exercised the full pipeline: preprocessor expanded <cstdio>, the frontend parsed the C++, the backend emitted arm64 machine code, the assembler converted it to a Mach-O object file, and ld linked it into an executable.

Next

02-install-cmake-and-ninja.md