Skip to content

Instantly share code, notes, and snippets.

@parsa
Created January 24, 2026 15:17
Show Gist options
  • Select an option

  • Save parsa/15d230729ef771c60f05738c759676ca to your computer and use it in GitHub Desktop.

Select an option

Save parsa/15d230729ef771c60f05738c759676ca to your computer and use it in GitHub Desktop.
LLVM/Clang 23 PGO on macOS Tahoe 26.2
#!/usr/bin/env bash
set -euo pipefail
# Build & install the LLVM/Clang "stage2" PGO toolchain we ended up with
# in this conversation (macOS arm64): clang/clang++ + lld + lldb + compiler-rt +
# libc++/libc++abi/libunwind + OpenMP (libomp), installed to ~/.local/llvm/23.
#
# Prereqs (macOS):
# - Xcode + Command Line Tools installed (xcode-select --install)
# - CMake + Ninja available on PATH (e.g. brew install cmake ninja)
# - Python 3 available on PATH
#
# Usage:
# bash $HOME/Repositories/llvm-project/build_llvm23_pgo_arm64.sh
#
# Optional env overrides:
# LLVM_PROJECT_ROOT=/path/to/llvm-project
# BUILD_DIR=/path/to/build-pgo
# INSTALL_PREFIX=$HOME/.local/llvm/23
# JOBS=$(sysctl -n hw.ncpu)
# CLEAN=1 # wipe build dir first
LLVM_PROJECT_ROOT="${LLVM_PROJECT_ROOT:-$HOME/Repositories/llvm-project}"
SRC_DIR="${LLVM_PROJECT_ROOT}/llvm"
CACHE_FILE="${LLVM_PROJECT_ROOT}/clang/cmake/caches/Release.cmake"
BUILD_DIR="${BUILD_DIR:-${LLVM_PROJECT_ROOT}/build-pgo}"
INSTALL_PREFIX="${INSTALL_PREFIX:-${HOME}/.local/llvm/23}"
JOBS="${JOBS:-$(sysctl -n hw.ncpu)}"
command -v cmake >/dev/null
command -v ninja >/dev/null
command -v python3 >/dev/null
if [[ "${CLEAN:-0}" == "1" ]]; then
rm -rf "${BUILD_DIR}"
fi
mkdir -p "${BUILD_DIR}"
mkdir -p "${INSTALL_PREFIX}"
# Notes:
# - We use clang/cmake/caches/Release.cmake (NOT PGO.cmake). Release.cmake’s PGO
# pipeline avoids the macOS libc++/PGO instrumentation trap by building only
# compiler-rt in the instrumented stage and then doing a final stage2 build.
# - Put -D LLVM_RELEASE_* before -C Release.cmake (per Release.cmake docs).
cmake -G Ninja \
-S "${SRC_DIR}" \
-B "${BUILD_DIR}" \
-D LLVM_RELEASE_ENABLE_PGO=ON \
-D LLVM_RELEASE_ENABLE_LTO=THIN \
-D LLVM_RELEASE_ENABLE_PROJECTS="clang;lld;lldb;clang-tools-extra;mlir;polly" \
-D LLVM_RELEASE_ENABLE_RUNTIMES="compiler-rt;libcxx;libcxxabi;libunwind;openmp" \
-D LLVM_TARGETS_TO_BUILD="AArch64" \
-D BOOTSTRAP_LLVM_TARGETS_TO_BUILD="AArch64" \
-D BOOTSTRAP_BOOTSTRAP_LLVM_TARGETS_TO_BUILD="AArch64" \
-D CMAKE_OSX_ARCHITECTURES="arm64" \
-D COMPILER_RT_SUPPORTED_ARCH="arm64" \
-D BOOTSTRAP_COMPILER_RT_SUPPORTED_ARCH="arm64" \
-D BOOTSTRAP_BOOTSTRAP_COMPILER_RT_SUPPORTED_ARCH="arm64" \
-D COMPILER_RT_ENABLE_IOS=OFF \
-D COMPILER_RT_ENABLE_TVOS=OFF \
-D COMPILER_RT_ENABLE_WATCHOS=OFF \
-D COMPILER_RT_ENABLE_MACCATALYST=OFF \
-D BOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF \
-D BOOTSTRAP_COMPILER_RT_ENABLE_TVOS=OFF \
-D BOOTSTRAP_COMPILER_RT_ENABLE_WATCHOS=OFF \
-D BOOTSTRAP_COMPILER_RT_ENABLE_MACCATALYST=OFF \
-D BOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF \
-D BOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_TVOS=OFF \
-D BOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_WATCHOS=OFF \
-D BOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_MACCATALYST=OFF \
-D LLVM_INCLUDE_TESTS=OFF \
-D CLANG_INCLUDE_TESTS=OFF \
-D LLDB_INCLUDE_TESTS=OFF \
-D LLDB_USE_SYSTEM_DEBUGSERVER=ON \
-C "${CACHE_FILE}"
# Full PGO pipeline: stage1 -> stage2-instrumented (profile gen) -> stage2 (final)
ninja -C "${BUILD_DIR}" -j "${JOBS}" stage2
STAGE2_BINS="${BUILD_DIR}/tools/clang/stage2-instrumented-bins/tools/clang/stage2-bins"
if [[ ! -d "${STAGE2_BINS}" ]]; then
echo "ERROR: expected stage2 build dir not found: ${STAGE2_BINS}" >&2
exit 1
fi
cmake --install "${STAGE2_BINS}" --prefix "${INSTALL_PREFIX}"
cat <<EOF
Installed PGO toolchain to:
${INSTALL_PREFIX}
Use it via:
export PATH="${INSTALL_PREFIX}/bin:\$PATH"
Sanity checks:
${INSTALL_PREFIX}/bin/clang++ --version
${INSTALL_PREFIX}/bin/ld64.lld --version
${INSTALL_PREFIX}/bin/lldb --version
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment