Skip to content

Commit 03d8e59

Browse files
committed
Extension: ccache-remote
Enables ccache with remote Redis storage for sharing compilation cache across build hosts
1 parent 70840db commit 03d8e59

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed

extensions/ccache-remote.sh

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Extension: ccache-remote
2+
# Enables ccache with remote Redis storage for sharing compilation cache across build hosts
3+
#
4+
# Documentation: https://ccache.dev/howto/redis-storage.html
5+
# See also: https://ccache.dev/manual/4.10.html#config_remote_storage
6+
#
7+
# Usage:
8+
# # With Avahi/mDNS auto-discovery:
9+
# ./compile.sh ENABLE_EXTENSIONS=ccache-remote BOARD=...
10+
#
11+
# # With explicit Redis server (no Avahi needed):
12+
# ./compile.sh ENABLE_EXTENSIONS=ccache-remote CCACHE_REMOTE_STORAGE="redis://192.168.1.65:6379" BOARD=...
13+
#
14+
# Automatically sets USE_CCACHE=yes
15+
#
16+
# CCACHE_REMOTE_STORAGE format (ccache 4.4+):
17+
# redis://HOST[:PORT][|attribute=value...]
18+
# Common attributes:
19+
# connect-timeout=N - connection timeout in milliseconds (default: 100)
20+
# operation-timeout=N - operation timeout in milliseconds (default: 10000)
21+
# Example: "redis://192.168.1.65:6379|connect-timeout=500"
22+
#
23+
# Avahi/mDNS auto-discovery:
24+
# This extension tries to resolve 'ccache.local' hostname via mDNS.
25+
# To publish this hostname on Redis server, run:
26+
# avahi-publish-address -R ccache.local <SERVER_IP>
27+
# Or create a systemd service (see below).
28+
#
29+
# Server setup example:
30+
# 1. Install: apt install redis-server avahi-daemon avahi-utils
31+
# 2. Configure Redis (/etc/redis/redis.conf):
32+
# bind 0.0.0.0 ::
33+
# protected-mode no
34+
# maxmemory 4G
35+
# maxmemory-policy allkeys-lru
36+
# WARNING: This configuration is INSECURE - Redis is open without authentication.
37+
# Use ONLY in a fully trusted private network with no internet access.
38+
# For secure setup (password, TLS, ACL), see: https://redis.io/docs/management/security/
39+
# 3. Publish hostname (replace IP_ADDRESS with actual IP):
40+
# avahi-publish-address -R ccache.local IP_ADDRESS
41+
# Or as systemd service /etc/systemd/system/ccache-hostname.service:
42+
# [Unit]
43+
# Description=Publish ccache.local hostname via Avahi
44+
# After=avahi-daemon.service redis-server.service
45+
# BindsTo=redis-server.service
46+
# [Service]
47+
# Type=simple
48+
# ExecStart=/usr/bin/avahi-publish-address -R ccache.local IP_ADDRESS
49+
# Restart=on-failure
50+
# [Install]
51+
# WantedBy=redis-server.service
52+
#
53+
# Client requirements for mDNS:
54+
# - systemd-resolved (modern systems), or
55+
# - libnss-mdns package with /etc/nsswitch.conf containing "mdns" in hosts line
56+
#
57+
# Fallback behavior:
58+
# If CCACHE_REMOTE_STORAGE is not set and ccache.local is not resolvable,
59+
# extension silently falls back to local ccache only.
60+
61+
# Query Redis stats (keys count and memory usage)
62+
function get_redis_stats() {
63+
local ip="$1"
64+
local port="${2:-6379}"
65+
local stats=""
66+
67+
if command -v redis-cli &>/dev/null; then
68+
local keys mem
69+
keys=$(timeout 2 redis-cli -h "$ip" -p "$port" DBSIZE 2>/dev/null | grep -oE '[0-9]+')
70+
mem=$(timeout 2 redis-cli -h "$ip" -p "$port" INFO memory 2>/dev/null | grep "used_memory_human" | cut -d: -f2 | tr -d '[:space:]')
71+
if [[ -n "$keys" ]]; then
72+
stats="keys=${keys:-0}, mem=${mem:-?}"
73+
fi
74+
else
75+
# Fallback: try netcat for basic connectivity check
76+
if nc -z -w 2 "$ip" "$port" 2>/dev/null; then
77+
stats="reachable (redis-cli not installed for detailed stats)"
78+
fi
79+
fi
80+
echo "$stats"
81+
}
82+
83+
# This runs on the HOST before Docker is launched.
84+
# Resolves 'ccache.local' via mDNS (requires Avahi on server publishing this hostname
85+
# with: avahi-publish-address -R ccache.local <IP>) and passes the resolved IP
86+
# to Docker container via CCACHE_REMOTE_STORAGE environment variable.
87+
# mDNS resolution doesn't work inside Docker, so we must resolve on host.
88+
function add_host_dependencies__setup_remote_ccache_for_docker() {
89+
# Skip if already configured explicitly
90+
if [[ -n "${CCACHE_REMOTE_STORAGE}" ]]; then
91+
display_alert "Remote ccache pre-configured" "${CCACHE_REMOTE_STORAGE}" "info"
92+
declare -g -a DOCKER_EXTRA_ARGS+=("--env" "CCACHE_REMOTE_STORAGE=${CCACHE_REMOTE_STORAGE}")
93+
return 0
94+
fi
95+
96+
# Try to resolve ccache.local via mDNS on the host
97+
local ccache_ip
98+
ccache_ip=$(getent hosts ccache.local 2>/dev/null | awk '{print $1; exit}')
99+
100+
if [[ -n "${ccache_ip}" ]]; then
101+
display_alert "Remote ccache discovered on host" "redis://${ccache_ip}:6379" "info"
102+
103+
# Show Redis stats
104+
local stats
105+
stats=$(get_redis_stats "${ccache_ip}" 6379)
106+
if [[ -n "$stats" ]]; then
107+
display_alert "Remote ccache stats" "${stats}" "info"
108+
fi
109+
110+
# Pass to Docker via DOCKER_EXTRA_ARGS
111+
declare -g -a DOCKER_EXTRA_ARGS+=("--env" "CCACHE_REMOTE_STORAGE=redis://${ccache_ip}:6379|connect-timeout=500")
112+
else
113+
display_alert "Remote ccache not found on host" "ccache.local not resolvable via mDNS" "debug"
114+
fi
115+
}
116+
117+
# This runs inside Docker (or native build) during configuration
118+
function extension_prepare_config__setup_remote_ccache() {
119+
# Enable ccache automatically
120+
declare -g USE_CCACHE=yes
121+
122+
# If CCACHE_REMOTE_STORAGE was passed from host (via Docker env), it's already set
123+
if [[ -n "${CCACHE_REMOTE_STORAGE}" ]]; then
124+
display_alert "Remote ccache configured" "${CCACHE_REMOTE_STORAGE}" "info"
125+
return 0
126+
fi
127+
128+
# For native (non-Docker) builds, try to resolve here
129+
local ccache_ip
130+
ccache_ip=$(getent hosts ccache.local 2>/dev/null | awk '{print $1; exit}')
131+
132+
if [[ -n "${ccache_ip}" ]]; then
133+
export CCACHE_REMOTE_STORAGE="redis://${ccache_ip}:6379|connect-timeout=500"
134+
display_alert "Remote ccache discovered" "${CCACHE_REMOTE_STORAGE}" "info"
135+
else
136+
display_alert "Remote ccache not available" "using local cache only" "debug"
137+
fi
138+
139+
return 0
140+
}
141+
142+
# This hook runs right before kernel make - add CCACHE_REMOTE_STORAGE to make environment.
143+
# Required because kernel build uses 'env -i' which clears all environment variables.
144+
function kernel_make_config__add_ccache_remote_storage() {
145+
if [[ -n "${CCACHE_REMOTE_STORAGE}" ]]; then
146+
common_make_envs+=("CCACHE_REMOTE_STORAGE='${CCACHE_REMOTE_STORAGE}'")
147+
display_alert "Kernel make: added remote ccache" "${CCACHE_REMOTE_STORAGE}" "debug"
148+
fi
149+
}

0 commit comments

Comments
 (0)