01 — Day-1 macOS Setup (Apple Silicon, macOS Sequoia+ / macOS 16, verified July 2026)

Goal. In one focused ~2-hour sitting, take a clean Mac to a working modern C++20/23 dev environment with Homebrew LLVM 21+, CMake 3.28+, Ninja, Conan 2, VSCode, and a green first build.

Commands are copy-pasteable. Read each block before running it. Every version and path is verified for macOS 16 (Sequoia+) on Apple Silicon in July 2026.


§1. Xcode Command Line Tools (5 min)

You need Apple’s CLT for the macOS SDK headers and xcrun. You do not need full Xcode.app.

xcode-select --install

A dialog opens; click Install. Wait ~5 minutes.

Verify:

xcode-select -p
# expected: /Library/Developer/CommandLineTools

xcrun --sdk macosx --show-sdk-path
# expected: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk (or MacOSX16.sdk)

If xcode-select -p prints /Applications/Xcode.app/... you have full Xcode installed. That’s fine — the rest of this guide still works, but your SDK path will differ.


§2. Homebrew (5 min)

Install Homebrew:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

On Apple Silicon this installs to /opt/homebrew. The installer prints two eval lines at the end — run them and add the second to ~/.zshrc:

eval "$(/opt/homebrew/bin/brew shellenv)"
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zshrc

Verify:

brew --version
# expected: Homebrew 4.x.x (July 2026 baseline)

brew doctor
# expected: Your system is ready to brew.

If brew doctor complains about /usr/local vs /opt/homebrew, you have a leftover Intel install. Uninstall Intel Homebrew per the official docs before continuing. This is common on machines migrated from an Intel Mac via Migration Assistant.


§3. The Day-1 brew bundle (15–20 min)

One command installs everything:

brew install llvm cmake ninja git gh conan lldb \
             python@3.13 uv jq ripgrep fd fzf bat \
             cmake-language-server clang-format

Package roles:

Package

Role

Verified version July 2026

llvm

clang++ + libc++ + lld + clang-tidy

21.1.8

cmake

Build-system generator

3.30+

ninja

Fast build backend

1.12+

git

Newer than macOS system git

2.47+

gh

GitHub CLI

2.60+

conan

C++ package manager (Phase 4)

2.x

lldb

Newer than Apple lldb

matches LLVM 21

python@3.13

Base Python (for uv bootstrap)

3.13.x

uv

Astral’s fast Python manager (Phase 5)

0.5+

jq, ripgrep (rg), fd, fzf, bat

CLI ergonomics

latest

cmake-language-server

LSP for CMake in editor

latest

clang-format

Only needed if you don’t want to use LLVM’s bundled

matches LLVM 21

Total download: ~2.5 GB. Total on-disk: ~5 GB.

Do not add Homebrew Python to PATH ahead of system Python. uv handles Python versioning inside projects. Homebrew Python is only here to bootstrap uv.


§4. PATH setup — brew LLVM MUST win (10 min, critical)

macOS ships /usr/bin/clang++. Homebrew installs LLVM 21 to /opt/homebrew/opt/llvm/bin/clang++. Without a PATH override, the system clang wins and you get an ancient C++ standard library.

Append to ~/.zshrc:

cat >> ~/.zshrc <<'ZSHRC_APPEND'

# === Homebrew LLVM (brew LLVM must win over Apple Clang) ===
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"

# Compiler and linker flags so headers/libs resolve to brew LLVM's libc++
export LDFLAGS="-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind"
export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"

# Explicit compiler pointers (CMake honors these)
export CC="/opt/homebrew/opt/llvm/bin/clang"
export CXX="/opt/homebrew/opt/llvm/bin/clang++"

# macOS SDK sysroot — refresh when macOS major-updates
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"

# === End Homebrew LLVM block ===
ZSHRC_APPEND

source ~/.zshrc

Verify:

which clang++
# expected: /opt/homebrew/opt/llvm/bin/clang++

clang++ --version
# expected: Homebrew clang version 21.1.8 (or newer)
# Target: arm64-apple-darwin24.x.x (or newer)
# Thread model: posix
# InstalledDir: /opt/homebrew/opt/llvm/bin

If clang++ --version still says Apple clang version ..., your PATH export is not taking effect. Debug with:

echo $PATH | tr ':' '\n' | head
# Line 1 must be /opt/homebrew/opt/llvm/bin

If line 1 is anything else, another .zshrc line is overriding your export. Move the brew LLVM block to the very end of ~/.zshrc.

Test C++23 features are available

mkdir -p /tmp/cxxtest && cd /tmp/cxxtest
cat > test.cpp <<'CPP'
#include <expected>
#include <print>
#include <ranges>

std::expected<int, std::string> parse(std::string_view s) {
    if (s == "42") return 42;
    return std::unexpected{"nope"};
}

int main() {
    auto r = parse("42");
    std::print("value = {}\n", r.value_or(-1));

    auto squares = std::views::iota(1, 6)
                 | std::views::transform([](int x){ return x * x; });
    for (int x : squares) std::print("{} ", x);
    std::print("\n");
}
CPP

clang++ -std=c++23 -stdlib=libc++ test.cpp -o test
./test

Expected output:

value = 42
1 4 9 16 25

If this compiles and runs, brew LLVM is correctly installed. If <expected> or <print> is not found, you are still linking against Apple’s older libc++ — recheck the LDFLAGS, CPPFLAGS, and PATH in the previous block.


§5. Git and GitHub CLI (10 min)

git config --global user.name "Raghul R"
git config --global user.email "your.email@zohocorp.com"   # or personal
git config --global init.defaultBranch main
git config --global core.editor "code --wait"              # or 'nvim' etc.
git config --global pull.rebase true
git config --global fetch.prune true
git config --global rerere.enabled true
git config --global commit.gpgsign false                    # enable after §6

Generate an SSH key for GitHub:

ssh-keygen -t ed25519 -C "your.email@zohocorp.com" -f ~/.ssh/id_ed25519
eval "$(ssh-agent -s)"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

Add to macOS SSH config:

mkdir -p ~/.ssh
cat > ~/.ssh/config <<'SSH'
Host github.com
    AddKeysToAgent yes
    UseKeychain yes
    IdentityFile ~/.ssh/id_ed25519
SSH
chmod 600 ~/.ssh/config

Authenticate GitHub CLI and upload the key:

gh auth login
# Choose: GitHub.com → HTTPS → Yes (auth Git) → Login with web browser
# It opens your browser; complete the flow.

gh ssh-key add ~/.ssh/id_ed25519.pub --title "M-series MacBook — $(date +%Y-%m-%d)"

Verify:

ssh -T git@github.com
# expected: Hi <username>! You've successfully authenticated ...

Enable 2FA on GitHub via your authenticator app — do this in the browser. Non-negotiable.


§6. Editor: VSCode + extensions (15 min)

Install VSCode:

brew install --cask visual-studio-code

Install the extension bundle from CLI:

code --install-extension llvm-vs-code-extensions.vscode-clangd
code --install-extension vadimcn.vscode-lldb
code --install-extension ms-vscode.cmake-tools
code --install-extension twxs.cmake
code --install-extension usernamehw.errorlens
code --install-extension eamodio.gitlens
code --install-extension jeff-hykin.better-cpp-syntax
code --install-extension xaver.clang-format
code --install-extension streetsidesoftware.code-spell-checker

Do NOT install ms-vscode.cpptools (the Microsoft C/C++ extension). It fights clangd over hover, completion, and diagnostics. clangd wins for modern C++. Use only clangd for language intelligence.

Full VSCode config (settings.json, tasks.json, launch.json, .clangd, .clang-format, .clang-tidy) is documented in 02_vscode_config.md. Do that as a follow-up step; it takes ~20 min and locks in your production config.


§7. First green build — the “Hello, C++23” template (15 min)

Create a template project you’ll reuse for every phase:

mkdir -p ~/src/hello-cpp23 && cd ~/src/hello-cpp23

cat > CMakeLists.txt <<'CMAKE'
cmake_minimum_required(VERSION 3.28)
project(hello_cpp23 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Force libc++ (brew LLVM). Apple Clang would default here anyway,
# but we spell it out for reproducibility.
add_compile_options(-stdlib=libc++)
add_link_options(-stdlib=libc++)

# Warnings-as-errors, hardening
add_compile_options(-Wall -Wextra -Wpedantic -Werror
                    -Wshadow -Wnon-virtual-dtor -Wold-style-cast
                    -Wcast-align -Woverloaded-virtual -Wconversion
                    -Wsign-conversion -Wdouble-promotion -Wformat=2)

add_executable(hello src/main.cpp)
CMAKE

mkdir -p src
cat > src/main.cpp <<'CPP'
#include <print>
#include <ranges>
#include <vector>

int main() {
    std::print("Hello, C++23 from brew LLVM on Apple Silicon.\n");
    auto squares = std::views::iota(1, 6)
                 | std::views::transform([](int x){ return x * x; });
    std::vector<int> v(squares.begin(), squares.end());
    for (int x : v) std::print("{} ", x);
    std::print("\n");
    return 0;
}
CPP

cmake -B build -G Ninja
cmake --build build
./build/hello

Expected:

Hello, C++23 from brew LLVM on Apple Silicon.
1 4 9 16 25

Commit this to a new GitHub repo as your template:

git init && git add -A && git commit -m "Initial: C++23 template with brew LLVM"
gh repo create hello-cpp23 --public --source=. --push

You now own a green C++23 template you can gh repo clone at the start of every phase.


§8. Troubleshooting (5–30 min per issue)

8.1. #include <expected> — file not found

You are linking against Apple’s older libc++, not brew’s. Check:

clang++ -stdlib=libc++ -std=c++23 -v -E -x c++ - </dev/null 2>&1 | grep 'c++/v1'

The include search paths must contain /opt/homebrew/opt/llvm/include/c++/v1 before /Library/Developer/CommandLineTools/usr/include/c++/v1. If not, your LDFLAGS/CPPFLAGS from §4 aren’t sourced. Restart your terminal.

8.2. Linker error _main referenced from _start or SDK not found

After a macOS point update, the SDK path can shift:

sudo xcode-select --reset
xcode-select --install
export SDKROOT="$(xcrun --sdk macosx --show-sdk-path)"

Re-open your terminal. Rebuild.

8.3. dyld error at runtime: Library not loaded: @rpath/libc++.1.dylib

Brew LLVM’s libc++ isn’t in the loader’s search path. Two fixes:

Preferred (per-project). Add to your CMakeLists.txt:

set(CMAKE_INSTALL_RPATH "/opt/homebrew/opt/llvm/lib/c++")
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)

Fallback (env var). In ~/.zshrc:

export DYLD_LIBRARY_PATH="/opt/homebrew/opt/llvm/lib/c++:${DYLD_LIBRARY_PATH:-}"

The env var approach is discouraged in production but fine for a solo learner box.

8.4. Rosetta warning — “arm64 binary running under Rosetta”

You likely installed Homebrew in an Intel-emulated shell. Fix:

uname -m
# expected on Apple Silicon: arm64
# if it says x86_64, you're in a Rosetta terminal — exit and open a native one

Find Terminal.app in Finder, Cmd+I, uncheck “Open using Rosetta”, relaunch.

8.5. cmake --build build says “No C++ compiler could be identified”

CMake is not seeing your CXX. Try:

cmake -B build -G Ninja -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm/bin/clang++

Then permanently: verify §4 export CXX= line is present in ~/.zshrc AND that you sourced it.

8.6. brew install llvm extremely slow or times out

You are being rate-limited by GitHub or CDN. Try:

brew install --HEAD llvm    # avoids GHCR bottle cache
# OR
HOMEBREW_NO_INSTALL_FROM_API=1 brew install llvm

Or wait for a lower-traffic time window (IST 07:00–10:00 is fastest from India).

8.7. VSCode’s clangd shows red squigglies but cmake --build succeeds

clangd needs compile_commands.json. Two fixes:

  • Ensure CMAKE_EXPORT_COMPILE_COMMANDS ON in CMakeLists.txt (already set in §7).

  • Symlink it to the project root:

    ln -sf build/compile_commands.json compile_commands.json
    
  • Restart clangd: Cmd+Shift+Pclangd: Restart language server.

Full clangd config is in 02_vscode_config.md.


§9. Verification checklist — sign off Day 1

Copy this checklist. If every line is a green ✅ you are done.

  • xcode-select -p prints a valid CLT path

  • brew doctor says “ready to brew”

  • which clang++ shows /opt/homebrew/opt/llvm/bin/clang++

  • clang++ --version shows Homebrew clang 21.x or newer

  • cmake --version shows 3.28+

  • ninja --version shows 1.12+

  • git config --global user.email shows the right address

  • ssh -T git@github.com says “successfully authenticated”

  • gh auth status shows logged in

  • hello binary from §7 prints correctly

  • hello-cpp23 template is pushed to your GitHub

  • ~/.zshrc has the LLVM block AND the brew shellenv line

  • Terminal.app is NOT running under Rosetta (uname -marm64)

If all boxes are green, you have a working environment for Phase 0–7.


§10. What you did NOT do today

  • You did not install CLion. That’s 03_clion_alternative.md. Optional.

  • You did not install Docker/OrbStack. That’s 04_docker_and_devcontainers.md. Needed by Phase 4.

  • You did not set up cloud GPU. That’s 05_cloud_and_gpu_access.md. Needed by Phase 5.

  • You did not configure VSCode dotfiles beyond installing extensions. That’s 02_vscode_config.md. Do it Day 2 (30 min).

  • You did not install vcpkg. Deliberate — wait until Phase 4.