Skip to content

build: PCH + ccache launcher + fast-linker autodetect #255

build: PCH + ccache launcher + fast-linker autodetect

build: PCH + ccache launcher + fast-linker autodetect #255

Workflow file for this run

name: CI
on:
push:
branches: [main]
paths-ignore:
- "**/*.md"
- "docs/**"
- ".gitignore"
pull_request:
branches: [main]
paths-ignore:
- "**/*.md"
- "docs/**"
- ".gitignore"
# Lets a branch run the (billed) macOS leg on demand for validation without
# merging to main — see the macos job's event-name guard below.
workflow_dispatch:
# Cancel superseded runs on the same ref. A force-push to a PR kills the
# in-flight run instead of stacking a second full matrix.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
# ---------------------------------------------------------------------------
# Linux — self-hosted (wsl-linux). $0 billed. Uses the host's persistent
# vcpkg + ccache dirs (survive across runs), so NO GitHub Actions cache is
# consumed. Tools (gcc-13, clang-18, ninja, ccache) are pre-installed on the
# host; the guard installs only if a reimage drops them.
# ---------------------------------------------------------------------------
linux:
runs-on: [self-hosted, linux, lci-linux]
strategy:
fail-fast: false
matrix:
include:
- { cc: gcc-13, cxx: g++-13, preset: release }
- { cc: clang-18, cxx: clang++-18, preset: release }
- { cc: gcc-13, cxx: g++-13, preset: debug }
# Sanitizers are expensive — main only.
- { cc: gcc-13, cxx: g++-13, preset: sanitizer, main_only: true }
- { cc: gcc-13, cxx: g++-13, preset: tsan, main_only: true }
name: linux ${{ matrix.cc }} / ${{ matrix.preset }}
steps:
- uses: actions/checkout@v4
# zip/unzip/curl/tar are required by bootstrap-vcpkg.sh.
- name: Ensure build tools
run: |
need=""
for t in ninja ccache zip unzip curl tar "${{ matrix.cc }}" "${{ matrix.cxx }}"; do
command -v "$t" >/dev/null || need="$need $t"
done
if [ -n "$need" ]; then
sudo apt-get update
sudo apt-get install -y ninja-build ccache zip unzip curl tar "${{ matrix.cc }}" "${{ matrix.cxx }}"
fi
- name: Set up vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"
- name: Configure
if: ${{ !matrix.main_only || github.ref == 'refs/heads/main' }}
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
run: |
cmake --preset ${{ matrix.preset }} \
-G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
- name: Dump vcpkg logs on failure
if: failure()
run: |
echo "===== vcpkg-manifest-install.log ====="
cat build/${{ matrix.preset }}/vcpkg-manifest-install.log 2>/dev/null || true
for f in "$VCPKG_ROOT"/buildtrees/*/install-*-out.log \
"$VCPKG_ROOT"/buildtrees/*/config-*-out.log; do
[ -f "$f" ] || continue
echo "===== $f (last 200 lines) ====="
tail -n 200 "$f"
done
- name: Build
if: ${{ !matrix.main_only || github.ref == 'refs/heads/main' }}
run: cmake --build build/${{ matrix.preset }} --parallel
# ctest disabled until pre-existing failures triaged (see MEMORY.md
# preexisting-test-failures). Run locally: ctest --test-dir build/<preset>.
- name: Test (disabled — manual until pre-existing failures fixed)
if: false
run: ctest --test-dir build/${{ matrix.preset }} --output-on-failure --parallel
- name: Build diff-engine unit tests
if: matrix.preset == 'release'
run: cmake --build build/release --target parity_unit_tests --parallel
- name: Prep test corpora
if: matrix.preset == 'release'
run: ./tests/parity/corpora/prep_real.sh
- name: Run diff-engine unit tests
if: matrix.preset == 'release'
run: |
cd build/release
ctest -L diff --output-on-failure --parallel $(nproc)
# Free the build tree after the run so the self-hosted host doesn't
# accumulate per-preset build dirs across the matrix. ccache + vcpkg
# caches (the slow parts) persist; only object files are dropped.
- name: Reclaim build space
if: always()
run: rm -rf build/${{ matrix.preset }}
# ---------------------------------------------------------------------------
# Windows — self-hosted (win-host). $0 billed. Requires MSVC (VS Build
# Tools), CMake, and Ninja on PATH on the host. Release only.
# ---------------------------------------------------------------------------
windows:
runs-on: [self-hosted, windows, lci-windows]
name: windows msvc / release
steps:
- uses: actions/checkout@v4
- name: Set up vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"
- name: Configure
run: |
cmake --preset release `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
- name: Dump vcpkg logs on failure
if: failure()
run: |
$log = "build/release/vcpkg-manifest-install.log"
if (Test-Path $log) { Write-Output "===== $log ====="; Get-Content $log }
Get-ChildItem -Path "$env:VCPKG_ROOT/buildtrees" -Recurse -Filter "*-out.log" -ErrorAction SilentlyContinue |
ForEach-Object {
Write-Output "===== $($_.FullName) (last 200 lines) ====="
Get-Content $_.FullName -Tail 200
}
- name: Build
run: cmake --build build/release --parallel --config Release
# Windows unit gate: the full lci_tests suite plus spec_diff. The seven
# suites previously excluded here (followups #4) are re-enabled now that
# both root causes are fixed:
# * ServerTest / ClientTest — the fixtures were Unix-domain-socket shaped
# (httplib AF_UNIX, a .sock file path) and the Windows transport is TCP
# (localhost:<port>); a .sock path's drive-letter colon also made the
# server's port parse throw in SetUp. The fixtures now take a
# platform-correct address via tests/helpers/test_socket.h.
# * GitReportToJson / CodeInsightGitTest / *HandlerFixture /
# ExploreIndexTestFixture — depended on report_to_json's POSIX-shaped
# path normalization (std::filesystem::relative treats a '/'-rooted
# path as non-absolute on Windows). normalize_rel is now a purely
# lexical, separator-independent string operation (git/serialize.cpp).
# The fork/exec integration + parity + benchmark suites remain gated off
# Windows in tests/CMakeLists.txt (no fork/exec port yet).
- name: Test (unit suite)
run: |
& build/release/tests/Release/lci_tests.exe
if ($LASTEXITCODE -ne 0) { throw "lci_tests failed ($LASTEXITCODE)" }
$spec = Get-ChildItem -Path build/release -Recurse -Filter spec_diff_unit_tests.exe | Select-Object -First 1
if (-not $spec) { throw "spec_diff_unit_tests.exe not found" }
& $spec.FullName
if ($LASTEXITCODE -ne 0) { throw "spec_diff_unit_tests failed ($LASTEXITCODE)" }
- name: Reclaim build space
if: always()
run: if (Test-Path build/release) { Remove-Item -Recurse -Force build/release }
# ---------------------------------------------------------------------------
# macOS — GitHub-hosted, the ONLY billed runner (10x). Restricted to pushes
# on main + tags so PR iterations never touch it. Keeps GH caches (ephemeral
# runner needs them) but uploads NO artifacts.
# ---------------------------------------------------------------------------
macos:
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
runs-on: macos-latest
name: macos appleclang / release
env:
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
steps:
- uses: actions/checkout@v4
- name: Export GitHub Actions cache variables
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set up vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"
- name: Set up ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: macos-appleclang-release
max-size: 500M
- name: Install tools
run: brew install ninja ccache
- name: Configure
run: |
cmake --preset release \
-G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
# Surface vcpkg port build failures in the job log — by default the
# compiler diagnostics land in buildtrees/*/install-*-out.log, which is
# never uploaded, making configure failures undiagnosable.
- name: Dump vcpkg logs on failure
if: failure()
run: |
echo "===== vcpkg-manifest-install.log ====="
cat build/release/vcpkg-manifest-install.log 2>/dev/null || true
for f in "$VCPKG_ROOT"/buildtrees/*/install-*-out.log \
"$VCPKG_ROOT"/buildtrees/*/config-*-out.log; do
[ -f "$f" ] || continue
echo "===== $f (last 200 lines) ====="
tail -n 200 "$f"
done
- name: Build
run: cmake --build build/release --parallel
# patch-efsw.cmake patch 2 fixed the FSEvents teardown abort (exit 134),
# so the whole FileWatcherTest suite no longer needs excluding — 8/9 pass
# on macOS (start/stop/create/modify/recursive/double-stop).
# One narrow exclusion remains:
# * DetectsFileDelete — efsw's FSEvents backend delivers an event on
# unlink but does not classify it as Action::Delete (its handleAddModDel
# gates Delete on flags&ItemRemoved && !exists; the real flag bits need
# observing on-device via efDEBUG). Create/Modify detection works.
# Tracked follow-up; not the teardown crash.
- name: Test (unit suite)
run: ./build/release/tests/lci_tests "--gtest_filter=-FileWatcherTest.DetectsFileDelete"
# ---------------------------------------------------------------------------
# Benchmarks — self-hosted Linux, main only. Numbers go to the job log; no
# artifact upload (was retention 30 — pure GH storage).
# ---------------------------------------------------------------------------
benchmarks:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: [self-hosted, linux, lci-linux]
name: benchmarks
steps:
- uses: actions/checkout@v4
- name: Set up vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: "f3e10653cc27d62a37a3763cd84b38bca07c6075"
- name: Configure
env:
CC: gcc-13
CXX: g++-13
run: |
cmake --preset release \
-G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
- name: Dump vcpkg logs on failure
if: failure()
run: |
echo "===== vcpkg-manifest-install.log ====="
cat build/release/vcpkg-manifest-install.log 2>/dev/null || true
for f in "$VCPKG_ROOT"/buildtrees/*/install-*-out.log \
"$VCPKG_ROOT"/buildtrees/*/config-*-out.log; do
[ -f "$f" ] || continue
echo "===== $f (last 200 lines) ====="
tail -n 200 "$f"
done
- name: Build benchmarks
run: cmake --build build/release --target lci_benchmarks --parallel
- name: Run benchmarks
run: |
./build/release/tests/lci_benchmarks \
--benchmark_format=console \
--benchmark_min_time=0.1s | tee benchmark_results.txt
- name: Reclaim build space
if: always()
run: rm -rf build/release benchmark_results.txt