[build] Add ccache support for C/C++ compilation (SONIC_CONFIG_USE_CCACHE)#25650
[build] Add ccache support for C/C++ compilation (SONIC_CONFIG_USE_CCACHE)#25650rustiqly wants to merge 1 commit intosonic-net:masterfrom
Conversation
|
@copilot review |
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Adds an opt-in SONIC_CONFIG_USE_CCACHE build knob to integrate ccache into the SONiC build environment, aiming to speed up incremental C/C++ rebuilds by caching compilation outputs.
Changes:
- Introduces
SONIC_CONFIG_USE_CCACHEconfiguration option (defaultn). - Installs
ccachein the bookworm and trixie sonic-slave images. - Injects a
CCACHE_ENVprefix into Debian package build commands and addsccache-stats/ccache-clearhelper targets.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
rules/config |
Adds SONIC_CONFIG_USE_CCACHE knob and documentation comment. |
slave.mk |
Defines CCACHE_ENV, prefixes build commands, prints knob value, and adds ccache helper targets. |
sonic-slave-bookworm/Dockerfile.j2 |
Installs ccache in the bookworm build container. |
sonic-slave-trixie/Dockerfile.j2 |
Installs ccache in the trixie build container. |
slave.mk
Outdated
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=000 | ||
| $(shell mkdir -p $(TARGET_PATH)/ccache/$(BLDENV) && chmod 777 $(TARGET_PATH)/ccache/$(BLDENV)) |
There was a problem hiding this comment.
CCACHE_DIR is set as a relative path ("$(TARGET_PATH)/ccache/$(BLDENV)"). Since the build recipes run sub-builds in other working directories (e.g., make -C ... and pushd $($*_SRC_PATH)), ccache will resolve this relative to the package directory and end up writing to per-package src/.../target/ccache/... instead of the intended top-level target/ccache/..., which also makes ccache-stats misleading. Use an absolute path for CCACHE_DIR (e.g., based on $(PROJECT_ROOT) or $(abspath ...)) so all build steps share the same cache location.
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=000 | |
| $(shell mkdir -p $(TARGET_PATH)/ccache/$(BLDENV) && chmod 777 $(TARGET_PATH)/ccache/$(BLDENV)) | |
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(abspath $(TARGET_PATH)/ccache/$(BLDENV)) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=000 | |
| $(shell mkdir -p $(abspath $(TARGET_PATH)/ccache/$(BLDENV)) && chmod 777 $(abspath $(TARGET_PATH)/ccache/$(BLDENV))) |
There was a problem hiding this comment.
All addressed in latest push:
- CCACHE_DIR now uses
$(abspath ...)for a stable absolute path - Added
command -v ccacheguard that errors early if ccache is missing - Tightened UMASK from 000 to 022
ccache-statsuses the same$(CCACHE_DIR)variable- Hint now says
rules/config.userinstead ofrules/config
Thanks for the thorough review!
slave.mk
Outdated
| ############################################################################### | ||
| ccache-stats : | ||
| ifeq ($(SONIC_CONFIG_USE_CCACHE),y) | ||
| CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) ccache -s |
There was a problem hiding this comment.
ccache-stats uses a relative CCACHE_DIR ("$(TARGET_PATH)/ccache/$(BLDENV)"). If builds run from other working directories (e.g., sub-makes in package directories), this may not point at the same cache used during compilation. After switching CCACHE_DIR to an absolute path, update this target to match so the stats reflect the actual cache.
| CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) ccache -s | |
| CCACHE_DIR=$(CCACHE_DIR) ccache -s |
slave.mk
Outdated
| ifeq ($(SONIC_CONFIG_USE_CCACHE),y) | ||
| CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) ccache -s | ||
| else | ||
| @echo "ccache is not enabled. Set SONIC_CONFIG_USE_CCACHE=y in rules/config" |
There was a problem hiding this comment.
The message suggests editing rules/config to enable ccache, but user overrides are typically done via rules/config.user (which is included after rules/config) or via the make command line. Consider updating the hint so it doesn't encourage modifying the tracked rules/config file.
| @echo "ccache is not enabled. Set SONIC_CONFIG_USE_CCACHE=y in rules/config" | |
| @echo "ccache is not enabled. Set SONIC_CONFIG_USE_CCACHE=y in rules/config.user or pass SONIC_CONFIG_USE_CCACHE=y on the make command line" |
| # calls are intercepted by ccache symlinks. Cache is stored under target/ccache/ | ||
| # and persists across builds for near-instant recompilation of unchanged files. | ||
| CCACHE_ENV = | ||
| ifeq ($(SONIC_CONFIG_USE_CCACHE),y) |
There was a problem hiding this comment.
This enables ccache purely via PATH/CCACHE_* env vars, but ccache is only installed in the bookworm/trixie slave images in this PR. On other supported build envs (e.g., bullseye), enabling SONIC_CONFIG_USE_CCACHE=y will silently do nothing for compilation (no /usr/lib/ccache symlinks) and make ccache-stats will fail with ccache: command not found. Either install ccache in the other supported slave images as well, or add a guard that errors out early when ccache isn't available.
| ifeq ($(SONIC_CONFIG_USE_CCACHE),y) | |
| ifeq ($(SONIC_CONFIG_USE_CCACHE),y) | |
| ifeq ($(shell command -v ccache >/dev/null 2>&1 || echo notfound),notfound) | |
| $(error SONIC_CONFIG_USE_CCACHE=y but 'ccache' is not installed in the build environment. Install ccache in the slave image or unset SONIC_CONFIG_USE_CCACHE) | |
| endif |
slave.mk
Outdated
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=000 | ||
| $(shell mkdir -p $(TARGET_PATH)/ccache/$(BLDENV) && chmod 777 $(TARGET_PATH)/ccache/$(BLDENV)) |
There was a problem hiding this comment.
Setting CCACHE_UMASK=000 and applying chmod 777 to $(TARGET_PATH)/ccache/$(BLDENV) makes the ccache directory world-writable. On multi-user build hosts or shared workspaces, another local user who can traverse the repo can modify cached object files and have them reused in later builds, allowing injection of arbitrary code into built images/packages. Restrict the cache directory to the build user only (e.g., a per-user cache location with a tight umask and non-world-writable permissions) so other accounts cannot tamper with build artifacts.
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(TARGET_PATH)/ccache/$(BLDENV) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=000 | |
| $(shell mkdir -p $(TARGET_PATH)/ccache/$(BLDENV) && chmod 777 $(TARGET_PATH)/ccache/$(BLDENV)) | |
| CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(TARGET_PATH)/ccache/$(USER)/$(BLDENV) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=077 | |
| $(shell mkdir -p $(TARGET_PATH)/ccache/$(USER)/$(BLDENV) && chmod 700 $(TARGET_PATH)/ccache/$(USER)/$(BLDENV)) |
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
6faeb06 to
e85a3e6
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
e85a3e6 to
ba589dc
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
ba589dc to
02a21f5
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
02a21f5 to
2ce38e7
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
2ce38e7 to
0a346c7
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
0a346c7 to
2a307d3
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
2a307d3 to
0768cd0
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines successfully started running 1 pipeline(s). |
…ACHE) Add optional ccache integration to speed up incremental C/C++ builds. When SONIC_CONFIG_USE_CCACHE=y is set in rules/config, ccache intercepts gcc/g++ calls via /usr/lib/ccache PATH prepend and caches compilation results under target/ccache/<distro>/. Changes: - rules/config: Add SONIC_CONFIG_USE_CCACHE knob (default: n) - slave.mk: Define CCACHE_ENV with PATH, CCACHE_DIR, CCACHE_BASEDIR, and CCACHE_COMPILERCHECK; inject into dpkg-buildpackage and make build commands; add ccache-stats and ccache-clear targets; print config status in build info - sonic-slave-bookworm/Dockerfile.j2: Install ccache package - sonic-slave-trixie/Dockerfile.j2: Install ccache package Benefits: - First build populates the cache (minimal overhead from ccache lookups) - Subsequent builds with unchanged sources: near-instant recompilation - Key packages on the critical path (libswsscommon 2m, libsairedis 3m, swss 5m) benefit most from cache hits during iterative development - Cache is per-distro (bookworm/trixie) to avoid cross-contamination - CCACHE_COMPILERCHECK=content ensures cache validity across compiler updates Usage: echo 'SONIC_CONFIG_USE_CCACHE = y' >> rules/config.user make ccache-stats # view hit/miss statistics make ccache-clear # wipe cache Signed-off-by: Rustiqly <rustiqly@users.noreply.github.com>
0768cd0 to
cb588a6
Compare
|
/azp run Azure.sonic-buildimage |
|
Azure Pipelines failed to run 1 pipeline(s). |
Description
Add optional ccache integration to dramatically speed up incremental C/C++ builds. When
SONIC_CONFIG_USE_CCACHE=yis set, ccache intercepts gcc/g++ calls and caches object files, making recompilation of unchanged source near-instant.Motivation
The critical build path includes three C++ heavy packages:
These packages are on the serial critical path (libswsscommon → libsairedis → swss = ~10m). With a warm ccache, incremental rebuilds (e.g., when only one file changes in swss) drop from minutes to seconds.
Changes
rules/configSONIC_CONFIG_USE_CCACHEknob (default:n)slave.mkCCACHE_ENV, inject into build commands, addccache-stats/ccache-cleartargetssonic-slave-bookworm/Dockerfile.j2ccachepackagesonic-slave-trixie/Dockerfile.j2ccachepackageHow it works
ccacheis installed in the sonic-slave container (adds ~1MB)/usr/lib/ccacheis prepended toPATH— this directory contains symlinks (gcc,g++,cc,c++) that route through ccachetarget/ccache/<distro>/— persists across builds, per-distro to avoid cross-contaminationCCACHE_COMPILERCHECK=contentensures cache invalidation on compiler upgradesCCACHE_ENVis empty — zero impactUsage
Expected Impact
Backward Compatibility
n— no behavior change unless explicitly enabledccachepackage is installed but dormant when not enabledSONIC_DPKG_CACHE_METHOD) is orthogonal and works alongside ccacheTesting
Full VS build test pending with CI.