diff --git a/rules/config b/rules/config index 3e1ea29911e..52861900db2 100644 --- a/rules/config +++ b/rules/config @@ -396,3 +396,10 @@ BUILD_SKIP_TEST ?= n # but may use stale layers if base images changed without version bumps. # Recommended for local development; CI should leave this disabled. # SONIC_CONFIG_USE_DOCKER_CACHE = y + +# SONIC_CONFIG_USE_CCACHE - use ccache to speed up C/C++ compilation +# When enabled, ccache caches compilation results so that rebuilds of +# unchanged source files are near-instant. The cache is stored in +# target/ccache/ and persists across builds. +# Default: disabled (no impact on clean builds without a warm cache) +SONIC_CONFIG_USE_CCACHE ?= n diff --git a/slave.mk b/slave.mk index c1175f09891..e47c8d8377c 100644 --- a/slave.mk +++ b/slave.mk @@ -319,6 +319,19 @@ ifeq ($(SONIC_PROFILING_ON),y) DEB_BUILD_OPTIONS_GENERIC := nostrip noopt endif +# ccache configuration — prepend /usr/lib/ccache to PATH so that gcc/g++/cc/c++ +# 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) +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) +endif +CCACHE_DIR := $(abspath $(TARGET_PATH)/ccache/$(BLDENV)) +CCACHE_ENV = PATH=/usr/lib/ccache:$$PATH CCACHE_DIR=$(CCACHE_DIR) CCACHE_BASEDIR=$(BUILD_WORKDIR) CCACHE_COMPILERCHECK=content CCACHE_UMASK=022 +$(shell mkdir -p $(CCACHE_DIR)) +endif + ifeq ($(SONIC_BUILD_JOBS),) override SONIC_BUILD_JOBS := $(SONIC_CONFIG_BUILD_JOBS) endif @@ -431,6 +444,7 @@ $(info "SONIC_BUILD_JOBS" : "$(SONIC_BUILD_JOBS)") $(info "SONIC_CONFIG_MAKE_JOBS" : "$(SONIC_CONFIG_MAKE_JOBS)") $(info "USE_NATIVE_DOCKERD_FOR_BUILD" : "$(SONIC_CONFIG_USE_NATIVE_DOCKERD_FOR_BUILD)") $(info "USE_DOCKER_CACHE" : "$(SONIC_CONFIG_USE_DOCKER_CACHE)") +$(info "SONIC_CONFIG_USE_CCACHE" : "$(SONIC_CONFIG_USE_CCACHE)") $(info "USERNAME" : "$(USERNAME)") $(info "PASSWORD" : "$(PASSWORD)") $(info "CHANGE_DEFAULT_PASSWORD" : "$(CHANGE_DEFAULT_PASSWORD)") @@ -815,7 +829,7 @@ $(addprefix $(DEBS_PATH)/, $(SONIC_MAKE_DEBS)) : $(DEBS_PATH)/% : .platform $$(a if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && ( quilt pop -a -f 1>/dev/null 2>&1 || true ) && QUILT_PATCHES=../$(notdir $($*_SRC_PATH)).patch quilt push -a; popd; fi $(LOG) # Build project and take package $(SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR) - DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) make -j$(SONIC_CONFIG_MAKE_JOBS) DEST=$(shell pwd)/$(DEBS_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(DEBS_PATH)/$* $(LOG) + $(CCACHE_ENV) DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) make -j$(SONIC_CONFIG_MAKE_JOBS) DEST=$(shell pwd)/$(DEBS_PATH) -C $($*_SRC_PATH) $(shell pwd)/$(DEBS_PATH)/$* $(LOG) # Clean up if [ -f $($*_SRC_PATH).patch/series ]; then pushd $($*_SRC_PATH) && quilt pop -a -f; [ -d .pc ] && rm -rf .pc; popd; fi $(LOG) @@ -861,8 +875,8 @@ $(addprefix $(DEBS_PATH)/, $(SONIC_DPKG_DEBS)) : $(DEBS_PATH)/% : .platform $$(a if [ -f ./autogen.sh ]; then ./autogen.sh $(LOG); fi $(SETUP_OVERLAYFS_FOR_DPKG_ADMINDIR) $(if $($*_DPKG_TARGET), - ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" DEB_BUILD_PROFILES="${$*_DEB_BUILD_PROFILES}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) timeout --preserve-status -s 9 -k 10 $(BUILD_PROCESS_TIMEOUT) dpkg-buildpackage -rfakeroot -b $(ANT_DEB_CROSS_OPT) -us -uc -tc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) --admindir $$mergedir $(LOG), - ${$*_BUILD_ENV} DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" DEB_BUILD_PROFILES="${$*_DEB_BUILD_PROFILES}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) timeout --preserve-status -s 9 -k 10 $(BUILD_PROCESS_TIMEOUT) dpkg-buildpackage -rfakeroot -b $(ANT_DEB_CROSS_OPT) -us -uc -tc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $$mergedir $(LOG) + ${$*_BUILD_ENV} $(CCACHE_ENV) DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" DEB_BUILD_PROFILES="${$*_DEB_BUILD_PROFILES}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) timeout --preserve-status -s 9 -k 10 $(BUILD_PROCESS_TIMEOUT) dpkg-buildpackage -rfakeroot -b $(ANT_DEB_CROSS_OPT) -us -uc -tc -j$(SONIC_CONFIG_MAKE_JOBS) --as-root -T$($*_DPKG_TARGET) --admindir $$mergedir $(LOG), + ${$*_BUILD_ENV} $(CCACHE_ENV) DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS_GENERIC} ${$*_DEB_BUILD_OPTIONS}" DEB_BUILD_PROFILES="${$*_DEB_BUILD_PROFILES}" $(ANT_DEB_CONFIG) $(CROSS_COMPILE_FLAGS) timeout --preserve-status -s 9 -k 10 $(BUILD_PROCESS_TIMEOUT) dpkg-buildpackage -rfakeroot -b $(ANT_DEB_CROSS_OPT) -us -uc -tc -j$(SONIC_CONFIG_MAKE_JOBS) --admindir $$mergedir $(LOG) ) popd $(LOG_SIMPLE) # Clean up @@ -1867,15 +1881,20 @@ jessie : $$(addprefix $(TARGET_PATH)/,$$(JESSIE_DOCKER_IMAGES)) \ ############################################################################### ############################################################################### -## Build report — post-build timing and dependency analysis +## ccache targets ############################################################################### +ccache-stats : +ifeq ($(SONIC_CONFIG_USE_CCACHE),y) + CCACHE_DIR=$(CCACHE_DIR) ccache -s +else + @echo "ccache is not enabled. Set SONIC_CONFIG_USE_CCACHE=y in rules/config.user" +endif + +ccache-clear : + rm -rf $(TARGET_PATH)/ccache + @echo "ccache cleared" -build-report: - @echo "=== Generating build timing report ===" - @bash $(PROJECT_ROOT)/scripts/build-timing-report.sh $(TARGET_PATH) - @echo "" - @echo "=== Generating dependency graph analysis ===" - @python3 $(PROJECT_ROOT)/scripts/build-dep-graph.py $(PROJECT_ROOT) +.PHONY : ccache-stats ccache-clear .PHONY : $(SONIC_CLEAN_DEBS) $(SONIC_CLEAN_FILES) $(SONIC_CLEAN_PHONIES) $(SONIC_CLEAN_TARGETS) $(SONIC_CLEAN_STDEB_DEBS) $(SONIC_CLEAN_WHEELS) $(SONIC_PHONY_TARGETS) clean distclean configure build-report diff --git a/sonic-slave-bookworm/Dockerfile.j2 b/sonic-slave-bookworm/Dockerfile.j2 index 9d6ebe792b1..0c0f809089f 100644 --- a/sonic-slave-bookworm/Dockerfile.j2 +++ b/sonic-slave-bookworm/Dockerfile.j2 @@ -99,6 +99,7 @@ RUN apt-get update && apt-get install -y eatmydata && eatmydata apt-get install pigz \ git \ build-essential \ + ccache \ remake \ libtool \ lintian \ diff --git a/sonic-slave-trixie/Dockerfile.j2 b/sonic-slave-trixie/Dockerfile.j2 index 95499638d9d..8cfdf8e24a2 100644 --- a/sonic-slave-trixie/Dockerfile.j2 +++ b/sonic-slave-trixie/Dockerfile.j2 @@ -98,6 +98,7 @@ RUN apt-get update && apt-get install -y eatmydata && eatmydata apt-get install pigz \ git \ build-essential \ + ccache \ remake \ libtool \ lintian \