A system for accelerating Android Open Source Project (AOSP) builds by distributing compilation across multiple machines using distcc, sccache, and Redis.
- Overview
- Prerequisites
- Architecture
- Installation & Setup
- Configuration Details
- Troubleshooting
- Security Considerations
- Performance Tuning
- Advanced Usage
- Limitations
This project enables significant reduction in AOSP build times by leveraging multiple machines in a master-worker architecture:
- Master Node: Orchestrates builds, distributes compilation tasks
- Worker Nodes: Execute distributed compilation jobs
- Shared Cache: Redis-backed sccache for compiler cache sharing
- Source Synchronization: rsync-based source distribution
- distcc: Distributed C/C++ compiler
- distcc pump: Preprocessor distribution for improved performance
- sccache: Shared compiler cache with Redis backend
- Redis: Cache coordination server
- rsync: Efficient source code synchronization
All Machines (Master and Workers):
- Ubuntu/Debian Linux (apt-based)
- Same username across all machines
- sudo access
- Network connectivity between all machines
- OpenSSH server installed
Master Node:
- Minimum: 8GB RAM, 4 CPU cores
- Storage: Full AOSP source (~100GB) + build artifacts (~200GB)
- Network: Gigabit recommended for source distribution
Worker Nodes:
- Minimum: 4GB RAM, 2 CPU cores
- Storage: AOSP source directory (synced from master)
Required on Master:
# These will be installed by setup_master.sh
distcc, rsync, redis-server, openssh-client, sccacheRequired on Workers:
# These will be installed by setup_worker.sh
distcc, rsync, openssh-server- AOSP source code already downloaded on master node
- Recommended: Use
repotool to sync source before running setup
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Master │────▶│ Worker 1 │────▶│ Worker N │
│ Node │ │ Node │ │ Node │
│ │ │ │ │ │
│ - distcc │ │ - distccd │ │ - distccd │
│ - sccache │ │ - rsync │ │ - rsync │
│ - Redis │ │ │ │ │
│ - pump mode │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ AOSP Build Process │
│ │
│ 1. Source sync via rsync │
│ 2. Build orchestration via pump m │
│ 3. Distributed compilation via distcc │
│ 4. Shared caching via sccache + Redis │
└─────────────────────────────────────────────────────┘
Purpose: Enable bidirectional passwordless SSH access between all machines.
Run on Master Node:
./setup_passwordless_ssh.shPrompts:
- Username (must be same on all machines)
- SSH password (temporary, for initial setup)
- All machine IP addresses (space-separated, including master)
What happens:
- Generates Ed25519 SSH keys on all machines (if missing)
- Collects all public keys
- Distributes keys to all machines for bidirectional access
- Tests connectivity
Verification:
# From master
ssh username@worker1_ip hostname
ssh username@worker2_ip hostname
# Should return hostnames without password promptsPurpose: Install and configure master services (distcc, Redis, sccache).
Run on Master Node:
./setup_master.sh /path/to/your/aosp/sourceParameters:
/path/to/your/aosp/source: Absolute path to AOSP source directory
Prompts:
- Worker IP addresses (space-separated)
What happens:
- Installs dependencies: distcc, rsync, redis-server, openssh-client
- Downloads and installs sccache v0.8.2 to /usr/local/bin/
- Configures and starts Redis server
- Tests SSH connectivity to all workers
- Creates environment configuration at
$AOSP_DIR/.distbuild_env - Calculates job counts (8 for master + 64 per worker)
Generated Environment File (.distbuild_env):
export DISTCC_HOSTS="localhost/8 worker1_ip/lpf worker2_ip/lpf ..."
export DISTCC_PUMP=1
export USE_CCACHE=1
export CCACHE_EXEC=/usr/local/bin/sccache
export SCCACHE_REDIS="redis://localhost:6379"
export TOTAL_JOBS=136 # Example: 8 + (64 * 2 workers)
export WORKER_IPS="worker1_ip worker2_ip ..."Purpose: Install and configure worker services (distccd).
Run on EACH Worker Node:
./setup_worker.sh /path/to/your/aosp/sourceParameters:
/path/to/your/aosp/source: Same absolute path as on master
Prompts:
- Master IP address
What happens:
- Installs dependencies: distcc, rsync, openssh-server
- Auto-detects CPU cores and calculates job count (cores × 2)
- Configures
/etc/default/distcc:- Sets
allowedto master IP only - Sets
MAX_JOBSto calculated value
- Sets
- Starts and enables distccd service
- Creates AOSP directory if missing
Verification on Workers:
sudo systemctl status distccd
# Should show "active (running)"Purpose: Synchronize source and execute distributed build.
Run on Master Node:
./sync_and_build.shPrerequisites:
.distbuild_envmust exist (created by setup_master.sh)- Script assumes it's in parent directory of AOSP root
What happens:
- Sources the distributed build environment
- Syncs AOSP source to all workers via rsync (excludes: out/, .ccache/, .sccache/)
- Sources AOSP build environment
- Configures build target:
lunch aosp_arm64-eng - Starts distributed build:
pump m -j$TOTAL_JOBS - Displays sccache statistics after completion
Expected Output:
Syncing source to workers (excluding out/, caches)...
Syncing to 192.168.1.101...
Syncing to 192.168.1.102...
Starting build with -j136 (pump distcc + sccache)...
[Build output...]
Build complete. Stats: sccache --show-stats
Environment File (.distbuild_env)
# Host configuration for distributed compilation
export DISTCC_HOSTS="localhost/8 192.168.1.101/lpf 192.168.1.102/lpf"
export DISTCC_PUMP=1
# Cache configuration
export USE_CCACHE=1
export CCACHE_EXEC=/usr/local/bin/sccache
export SCCACHE_REDIS="redis://localhost:6379"
# Build configuration
export TOTAL_JOBS=136
export WORKER_IPS="192.168.1.101 192.168.1.102"Redis Configuration
- Default config:
/etc/redis/redis.conf - Port: 6379
- No password authentication (security consideration)
- Persistence disabled by default
distcc Configuration (/etc/default/distcc)
# Generated by setup_worker.sh
STARTDISTCC="true"
ALLOWEDNETS="192.168.1.100" # Master IP only
LISTENER="127.0.0.1" # Localhost
NICE="10"
ZEROCONF="false"
MAX_JOBS="8" # Auto-calculated: cores × 2# Test connectivity manually
ssh -o BatchMode=yes -o ConnectTimeout=5 worker_ip echo "OK"
# If fails, re-run passwordless setup
./setup_passwordless_ssh.sh# Check distccd status on workers
ssh worker_ip "sudo systemctl status distccd"
# Check if distccd is listening
ssh worker_ip "sudo netstat -tlnp | grep :3632"
# Test distcc from master
distcc --show-hosts# Check Redis status on master
sudo systemctl status redis-server
# Test Redis connectivity
redis-cli ping
# Should return "PONG"
# Check Redis logs
sudo journalctl -u redis-server -f# Check sccache status
sccache --show-stats
# Monitor distributed compilation
distccmon-text 1
# Check distcc logs
tail -f ~/.distcc/distcc.logMaster Node Debugging:
# Verify environment
source /path/to/aosp/.distbuild_env
echo $DISTCC_HOSTS
echo $TOTAL_JOBS
# Test Redis
redis-cli info keyspace
# Monitor sccache
sccache --show-stats --json | jq .
# Check distcc
distcc --version
distcc --show-hostsWorker Node Debugging:
# Check distccd logs
sudo journalctl -u distccd -f
# Check system load
htop
iostat -x 1
# Test distcc locally
echo "int main(){}" | distcc gcc -x c - -o /tmp/testNetwork Bottlenecks:
# Test network throughput
iperf3 -c worker_ip
# Monitor rsync sync times
rsync -a --stats --progress source/ worker_ip:dest/CPU/Memory Issues:
# Monitor CPU usage during build
htop
mpstat 1
# Check memory usage
free -h- SSH Keys: Bidirectional trust established via setup script
- Redis: No authentication, localhost only
- distccd: Allows master IP only, no encryption
- Password Exposure:
sshpassuses plaintext passwords temporarily
For Production Use:
- Network Isolation: Use VPN or private network
- Redis Security:
# Add password to redis.conf requirepass your_strong_password # Update .distbuild_env export SCCACHE_REDIS="redis://:password@localhost:6379"
- SSH Hardening:
# Use SSH keys only, disable password auth PasswordAuthentication no PermitRootLogin no - distcc Security:
# Use SSH tunnel for distcc traffic # Configure with DISTCC_HOSTS="@/8"
Current Approach: All-or-nothing bidirectional access
Alternative Approaches:
- Master-only SSH access (asymmetric keys)
- Network segmentation
- Per-service authentication
Current Formula:
- Master: 8 jobs
- Each Worker: 64 jobs (hardcoded assumption)
- Total:
8 + 64 × num_workers
Optimization:
# Detect actual worker cores
ssh worker_ip "nproc --all"
# Adjust MAX_JOBS in /etc/default/distcc
# Common formula: jobs = cores × 2rsync Tuning:
# For faster initial sync, modify sync_and_build.sh
rsync -a --delete --compress --stats \
--exclude='out/' --exclude='.ccache/' --exclude='.sccache/' \
"$AOSP_DIR"/ "$ip":"$AOSP_DIR"/Bandwidth Limiting:
# Limit rsync to 50MB/s
rsync --bwlimit=50000 ...Redis Persistence:
# Enable Redis persistence for cache durability
sudo sed -i 's/save ""/#save ""/' /etc/redis/redis.conf
sudo sed -i 's/#save 900 1/save 900 1/' /etc/redis/redis.conf
sudo systemctl restart redis-serversccache Tuning:
# Set cache size limits
export SCCACHE_CACHE_SIZE="10G"
export SCCACHE_MAX_FRAME_LEN=20000000Modify sync_and_build.sh:
# Replace hardcoded target
read -p "Enter build target (default: aosp_arm64-eng): " TARGET
TARGET=${TARGET:-"aosp_arm64-eng"}
lunch $TARGETBuild Specific Modules:
# After sourcing .distbuild_env
cd $AOSP_DIR
source build/envsetup.sh
lunch aosp_arm64-eng
pump m -j$TOTAL_JOBS frameworkReal-time Monitoring:
# Terminal 1: distcc monitoring
distccmon-text 1
# Terminal 2: build monitoring
watch -n 1 'sccache --show-stats'
# Terminal 3: system monitoring
htopLog Aggregation:
# Collect logs from all machines
mkdir -p logs
scp worker_ip:~/.distcc/distcc.log logs/distcc-worker1.log
scp worker2_ip:~/.distcc/distcc.log logs/distcc-worker2.log
journalctl -u distccd > logs/distccd-master.log- Ubuntu/Debian Only: Uses
aptpackage manager - Fixed Job Count: Workers hardcoded to 64 jobs
- Single Build Target: Hardcoded
aosp_arm64-eng - No Teardown: No cleanup script provided
- Network Assumption: Assumes gigabit or better network
- Security: Designed for trusted networks only
Network Bottleneck: Source distribution becomes bottleneck with many workers Memory Usage: Each worker needs full AOSP source in memory Diminishing Returns: Performance gains plateau after ~8-10 workers
Supported: Ubuntu 18.04+, Debian 10+ Unsupported: CentOS/RHEL, macOS, Windows Tested: AOSP master branch, Android 12+
For bug reports and feature requests, please use the project's issue tracker.
See LICENSE file for details.