
Build Acceleration
- 278 installs
- 155 repo stars
- Updated June 27, 2026
- mohitmishra786/low-level-dev-skills
Speed up native and Zig compile cycles using caching, parallel jobs, and linker tuning before slow CI pipelines block releases and local iteration.
About
Documents techniques to reduce compile and link latency for low-level projects via caching, parallelism, incremental toolchains, and CI configuration tuned for native codebases.
- Incremental compilation
- Build cache directories
- Parallel job tuning
- Link-time optimization tradeoffs
- CI cache strategies
Build Acceleration by the numbers
- 278 all-time installs (skills.sh)
- +19 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #346 of 1,435 DevOps & CI/CD skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mohitmishra786/low-level-dev-skills --skill build-accelerationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 278 |
|---|---|
| repo stars | ★ 155 |
| Last updated | June 27, 2026 |
| Repository | mohitmishra786/low-level-dev-skills ↗ |
What it does
Speed up native and Zig compile cycles using caching, parallel jobs, and linker tuning before slow CI pipelines block releases and local iteration.
Files
Build Acceleration
Purpose
Guide agents through reducing C/C++ build times using caching (ccache/sccache), distributed compilation (distcc), unity/jumbo builds, precompiled headers, split-DWARF for faster linking, and include pruning with IWYU.
Triggers
- "My C++ build is too slow — how do I speed it up?"
- "How do I set up ccache / sccache?"
- "How do precompiled headers work with CMake?"
- "How do I set up distributed compilation with distcc?"
- "How do I reduce link times with split-DWARF?"
- "How do I find which headers are slowing down compilation?"
Workflow
1. Diagnose the bottleneck first
# Time the full build
time cmake --build build -j$(nproc)
# Find the slowest TUs (CMake ≥3.16 with --profiling-output)
cmake -S . -B build -DCMAKE_CXX_FLAGS="-ftime-report"
cmake --build build 2>&1 | grep "Total" | sort -t: -k2 -rn | head -20
# Ninja build timings (use ninja -j1 for serial timing)
ninja -C build -j1 2>&1 | grep "^\[" | sort -t" " -k2 -rn | head -202. ccache — compiler cache
# Install
apt-get install ccache # Ubuntu/Debian
brew install ccache # macOS
# Check hit rate
ccache -s
# Configure cache size (default 5GB)
ccache -M 20G
# Invalidate cache if needed
ccache -CCMake integration (recommended over prefix hacks):
# CMakeLists.txt
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM})
endif()Key ~/.config/ccache/ccache.conf options:
max_size = 20G
compression = true
compression_level = 6
# For CI: share cache across jobs
cache_dir = /shared/ccache3. sccache — cloud-compatible cache (Rust, C/C++)
cargo install sccache
# Or: brew install sccache
# Set as compiler launcher
export RUSTC_WRAPPER=sccache # for Rust
export CMAKE_C_COMPILER_LAUNCHER=sccache # for CMake
# With S3 backend
export SCCACHE_BUCKET=my-build-cache
export SCCACHE_REGION=us-east-1
sccache --start-server
sccache --show-stats4. Precompiled headers (PCH)
PCH compiles a large header once and reuses the binary form.
# CMake ≥3.16 native PCH support
target_precompile_headers(mylib PRIVATE
<vector>
<string>
<unordered_map>
"myproject/common.h"
)
# Share PCH across targets (avoids recompilation)
target_precompile_headers(myapp REUSE_FROM mylib)// Traditional: stdafx.h / pch.h approach
// All TUs include pch.h as the very first include
// pch.h includes heavy system headers
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>PCH is most effective when headers are large and stable (STL, Boost, Qt). Avoid PCH for frequently-changing project headers.
5. Unity / jumbo builds
Combine multiple .cpp files into one TU to reduce header parsing overhead and improve inlining.
# CMake ≥3.16 unity build
set_target_properties(mylib PROPERTIES UNITY_BUILD ON)
# Control batch size (default 8 files per unity TU)
set_target_properties(mylib PROPERTIES UNITY_BUILD_BATCH_SIZE 16)
# Exclude specific files from unity (e.g., if they have ODR issues)
set_source_files_properties(problem.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)Manual unity file:
// unity_build.cpp
#include "module_a.cpp"
#include "module_b.cpp"
#include "module_c.cpp"Watch out for: anonymous namespaces (each TU has its own), using namespace in headers, duplicate static variables.
6. split-DWARF — reduce link time
Split DWARF puts debug info in .dwo sidecar files, dramatically reducing what the linker must process.
# GCC / Clang
gcc -g -gsplit-dwarf -o prog main.c
# CMake global
add_compile_options(-gsplit-dwarf)
# Combine .dwo files for distribution (optional)
dwp -o prog.dwp prog # GNU dwp toolPair with --gdb-index for faster GDB startup:
gcc -g -gsplit-dwarf -Wl,--gdb-index -o prog main.cLink time comparison (large project, typical): -g full DWARF ~4×–6× longer link vs -gsplit-dwarf.
7. distcc — distributed compilation
# Install on all machines
apt-get install distcc
# Start daemon on worker machines
distccd --daemon --allow 192.168.1.0/24 --jobs 8
# Client: set DISTCC_HOSTS
export DISTCC_HOSTS="localhost/4 worker1/8 worker2/8"
make -j20 CC="distcc gcc"
# CMake integration
set(CMAKE_C_COMPILER_LAUNCHER distcc)
set(CMAKE_CXX_COMPILER_LAUNCHER distcc)Stack with ccache: CC="ccache distcc gcc" — ccache checks local cache first, falls back to distcc.
8. Include pruning with IWYU
# Install
apt-get install iwyu
# Run via CMake
cmake -S . -B build -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=iwyu
cmake --build build 2>&1 | tee iwyu.log
# Apply fixes automatically
fix_include < iwyu.log --nosafe_headersSee skills/build-systems/include-what-you-use for full IWYU workflow.
For ccache configuration options, see references/ccache-config.md.
Related skills
- Use
skills/build-systems/cmakefor CMake project structure - Use
skills/build-systems/include-what-you-usefor IWYU header pruning - Use
skills/rust/rust-build-timesfor Rust-specific build acceleration - Use
skills/debuggers/dwarf-debug-formatfor split-DWARF internals
ccache Configuration Reference
Source: https://ccache.dev/manual/latest.html
Table of Contents
1. Configuration File Locations 2. Key Settings 3. CI / Shared Cache 4. Troubleshooting Hit Rate
Configuration File Locations
ccache reads config in order (later overrides earlier): 1. /etc/ccache.conf — system-wide 2. $CCACHE_CONFIGPATH — override path 3. ~/.config/ccache/ccache.conf — user config 4. $CCACHE_DIR/ccache.conf — per-cache-dir
Key Settings
# Cache storage
max_size = 20G # Maximum cache size (K, M, G, T suffix)
cache_dir = /var/cache/ccache # Non-default location
# Compression (significant space saving, slight CPU cost)
compression = true
compression_level = 6 # 1-9, default 6
# Debug (disable in production)
log_file = /tmp/ccache.log
debug = false
# Hashing behavior
hash_dir = false # Don't include CWD in hash (helps shared cache)
base_dir = /project # Strip this prefix from file paths in hash
# Include handling
sloppiness = include_file_mtime,include_file_ctime,time_macros
# time_macros: ignore __DATE__ and __TIME__ macro changes
# include_file_mtime: don't stat all included files (faster, slight risk)
# PCH support
sloppiness = pch_defines,time_macros # needed for GCC PCHCI / Shared Cache
For GitHub Actions / Jenkins with shared NFS:
# .github/workflows/build.yml
- name: Restore ccache
uses: actions/cache@v4
with:
path: ~/.cache/ccache
key: ccache-${{ runner.os }}-${{ hashFiles('**/CMakeLists.txt') }}
restore-keys: ccache-${{ runner.os }}-
- name: Configure ccache
run: |
ccache --set-config=max_size=500M
ccache --set-config=compression=true
ccache --set-config=hash_dir=false
ccache --set-config=base_dir=${{ github.workspace }}
- name: Build
run: cmake --build build -j$(nproc)
- name: ccache stats
run: ccache -sTroubleshooting Hit Rate
# Full stats
ccache -s -v
# Key miss reasons:
# "called for preprocessing" → compiler called as preprocessor, not supported
# "unsupported code directive" → inline asm or pragmas ccache can't handle
# "cache miss" → normal first-time compilation
# "preprocessor error" → fix the preprocessor invocation
# Reset statistics (not cache)
ccache --zero-stats
# Force a cache hit check without compilation
CCACHE_READONLY=1 makeCommon miss reasons and fixes:
| Miss reason | Fix |
|---|---|
| Absolute paths in source | Set base_dir to project root |
__DATE__/__TIME__ macros | Add time_macros to sloppiness |
| PCH changes invalidate all | Add pch_defines to sloppiness |
| Different working directory | Set hash_dir=false |
| Compiler version change | Expected — correct behavior |
Response files (@file) | Use CCACHE_COMPILERCHECK=content |