zed/script/setup-sccache
Yossi Eliaz c75b287a0e
Improve sccache cache reuse (#60968)
## Summary

- Upgrade sccache from 0.10.0 to 0.16.0 on macOS, Linux, and Windows CI
runners.
- Normalize the GitHub workspace with `SCCACHE_BASEDIRS` so identical
builds can reuse cache entries across checkout roots.
- Validate the cached binary version and stop an older server before
replacing it, including on Windows where a running executable cannot be
overwritten.

## Why

The setup scripts configured `SCCACHE_BASEDIR`, which sccache did not
use for cache-key path normalization. Absolute checkout paths therefore
remained part of cache keys and reduced reuse between CI workspaces.
sccache 0.16.0 supports `SCCACHE_BASEDIRS` and includes the Windows
path-normalization fix needed for the Windows runner.

## Validation

- `bash -n script/setup-sccache`
- `git diff --check`
- Upgraded a live local sccache 0.15.0 server to 0.16.0 through the
setup script.
- Compiled identical C sources from two checkout roots and observed one
cache miss followed by one cache hit.
- Confirmed that every release asset referenced by the setup scripts
exists for the supported CI runner targets.

Release Notes:

- N/A
2026-07-15 20:35:16 +00:00

144 lines
5 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
SCCACHE_VERSION="v0.16.0"
# Use absolute path to avoid issues with working directory changes between steps
SCCACHE_DIR="$(pwd)/target/sccache"
install_sccache() {
mkdir -p "$SCCACHE_DIR"
local expected_version="sccache ${SCCACHE_VERSION#v}"
local installed_version=""
if [[ -x "${SCCACHE_DIR}/sccache" ]]; then
if ! installed_version="$("${SCCACHE_DIR}/sccache" --version 2>/dev/null)"; then
echo "Cached sccache binary is invalid; reinstalling"
installed_version=""
fi
fi
if [[ "${installed_version}" == "${expected_version}" ]]; then
echo "sccache already cached: ${installed_version}"
else
if [[ -n "${installed_version}" ]]; then
echo "Stopping cached ${installed_version} server before upgrading..."
if ! "${SCCACHE_DIR}/sccache" --stop-server &>/dev/null; then
echo "No running sccache server to stop"
fi
fi
echo "Installing sccache ${SCCACHE_VERSION} from GitHub releases..."
local os arch archive basename
os="$(uname -s)"
arch="$(uname -m)"
case "${os}-${arch}" in
Darwin-arm64)
archive="sccache-${SCCACHE_VERSION}-aarch64-apple-darwin.tar.gz"
;;
Darwin-x86_64)
archive="sccache-${SCCACHE_VERSION}-x86_64-apple-darwin.tar.gz"
;;
Linux-x86_64)
archive="sccache-${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz"
;;
Linux-aarch64)
archive="sccache-${SCCACHE_VERSION}-aarch64-unknown-linux-musl.tar.gz"
;;
*)
echo "Unsupported platform: ${os}-${arch}"
exit 1
;;
esac
basename="${archive%.tar.gz}"
curl -fsSL "https://github.com/mozilla/sccache/releases/download/${SCCACHE_VERSION}/${archive}" | tar xz
mv "${basename}/sccache" "${SCCACHE_DIR}/"
rm -rf "${basename}"
echo "Installed sccache: $("${SCCACHE_DIR}/sccache" --version)"
fi
# Verify the binary works before adding to path
if ! "${SCCACHE_DIR}/sccache" --version &>/dev/null; then
echo "ERROR: sccache binary at ${SCCACHE_DIR}/sccache is not executable or corrupted"
rm -f "${SCCACHE_DIR}/sccache"
exit 1
fi
if [[ -n "${GITHUB_PATH:-}" ]]; then
echo "${SCCACHE_DIR}" >> "$GITHUB_PATH"
fi
export PATH="${SCCACHE_DIR}:${PATH}"
}
configure_sccache() {
if [[ -z "${R2_ACCOUNT_ID:-}" ]]; then
echo "R2_ACCOUNT_ID not set, skipping sccache configuration"
return
fi
echo "Configuring sccache with Cloudflare R2..."
local bucket="${SCCACHE_BUCKET:-sccache-zed}"
local key_prefix="${SCCACHE_KEY_PREFIX:-sccache/}"
local base_dir="${GITHUB_WORKSPACE:-$(pwd)}"
# Use the absolute path to sccache binary for RUSTC_WRAPPER to avoid
# any PATH race conditions between GITHUB_PATH and GITHUB_ENV
local sccache_bin="${SCCACHE_DIR}/sccache"
# Set in current process
export SCCACHE_ENDPOINT="https://${R2_ACCOUNT_ID}.r2.cloudflarestorage.com"
export SCCACHE_BUCKET="${bucket}"
export SCCACHE_REGION="auto"
export SCCACHE_S3_KEY_PREFIX="${key_prefix}"
export SCCACHE_BASEDIRS="${base_dir}"
export AWS_ACCESS_KEY_ID="${R2_ACCESS_KEY_ID}"
export AWS_SECRET_ACCESS_KEY="${R2_SECRET_ACCESS_KEY}"
export RUSTC_WRAPPER="${sccache_bin}"
# Also write to GITHUB_ENV for subsequent steps
if [[ -n "${GITHUB_ENV:-}" ]]; then
{
echo "SCCACHE_ENDPOINT=${SCCACHE_ENDPOINT}"
echo "SCCACHE_BUCKET=${SCCACHE_BUCKET}"
echo "SCCACHE_REGION=${SCCACHE_REGION}"
echo "SCCACHE_S3_KEY_PREFIX=${SCCACHE_S3_KEY_PREFIX}"
echo "SCCACHE_BASEDIRS=${SCCACHE_BASEDIRS}"
echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}"
echo "RUSTC_WRAPPER=${RUSTC_WRAPPER}"
} >> "$GITHUB_ENV"
fi
echo "✓ sccache configured with Cloudflare R2 (bucket: ${bucket})"
}
show_config() {
echo "=== sccache configuration ==="
echo "sccache version: $(sccache --version)"
echo "RUSTC_WRAPPER: ${RUSTC_WRAPPER:-<not set>}"
echo "SCCACHE_BUCKET: ${SCCACHE_BUCKET:-<not set>}"
echo "SCCACHE_ENDPOINT: ${SCCACHE_ENDPOINT:-<not set>}"
echo "SCCACHE_REGION: ${SCCACHE_REGION:-<not set>}"
echo "SCCACHE_S3_KEY_PREFIX: ${SCCACHE_S3_KEY_PREFIX:-<not set>}"
echo "SCCACHE_BASEDIRS: ${SCCACHE_BASEDIRS:-<not set>}"
if [[ -n "${AWS_ACCESS_KEY_ID:-}" ]]; then
echo "AWS_ACCESS_KEY_ID: <set, length=${#AWS_ACCESS_KEY_ID}>"
else
echo "AWS_ACCESS_KEY_ID: <not set>"
fi
if [[ -n "${AWS_SECRET_ACCESS_KEY:-}" ]]; then
echo "AWS_SECRET_ACCESS_KEY: <set>"
else
echo "AWS_SECRET_ACCESS_KEY: <not set>"
fi
echo "=== sccache stats ==="
sccache --show-stats || true
}
install_sccache
configure_sccache
show_config