Skip to content

refactor(compilation): extract ccache support into a swappable extension#9840

Open
iav wants to merge 8 commits into
armbian:mainfrom
iav:refactor/ccache-as-extension
Open

refactor(compilation): extract ccache support into a swappable extension#9840
iav wants to merge 8 commits into
armbian:mainfrom
iav:refactor/ccache-as-extension

Conversation

@iav

@iav iav commented May 17, 2026

Copy link
Copy Markdown
Contributor

Goal

Move ccache out of core compilation into a swappable extension. After this PR a parallel cache backend (sccache, distcc-style, distributed cache) can ship as a sibling extension without touching core.

A concrete near-term motivation: a future extensions/sccache.sh would let CI workflows running on GitHub-hosted runners route their compile-cache straight into the native GitHub Actions cache (SCCACHE_GHA_ENABLED=on, via mozilla-actions/sccache-action) — 10 GB free per repository, low-latency on the runner's local region. The same extension framework also covers self-hosted runners (S3/R2/MinIO bucket, WebDAV endpoint, Redis-on-disk, ...) without core changes — backend choice is purely an env-var concern per workflow.

What changes (vs armbian/build:main)

New files

  • extensions/ccache.sh — implements compile_prepare_vars, compile_wrapper_pre/_post, and {kernel,uboot,atf,crust}_make_config hooks.
  • lib/functions/compilation/compile-wrapper.shdo_with_compile_wrapper + compile_wrapper_pre/_post hooks.

Removed

  • lib/functions/compilation/ccache.sh (logic moved into the extension).

Modified

  • lib/functions/compilation/atf.sh — adds atf_make_config hook; replaces hardcoded ccache with ${CCACHE} (latent bug: USE_CCACHE=no was still dragging ccache into ATF).
  • lib/functions/compilation/crust.sh — adds crust_make_config hook; drops dead binutils_flags_crust="" declaration (preexisting SC2034 since 2023).
  • lib/functions/compilation/{kernel,uboot}.sh — compile phase wrapped in do_with_compile_wrapper; ${CCACHE:+${CCACHE} } guard avoids a leading space in CROSS_COMPILE when no cache backend is active (same guard in atf/crust).
  • lib/functions/configuration/compilation-config.sh — dispatches compile_prepare_vars instead of inlining configure-ccache; resets stale CCACHE between artifacts; emits a migration warning when USE_CCACHE/PRIVATE_CCACHE is set but no backend extension assigned CCACHE.
  • lib/functions/configuration/main-config.sh — whitespace normalization only (shfmt).
  • lib/functions/general/extensions.sh — adds extension_list_normalized helper (used by per-extension mutex checks).
  • lib/library-functions.sh — regenerated.
  • extensions/ccache-remote/ccache-remote.sh — now depends on the ccache backend extension via a top-level enable_extension "ccache", and drops the now-inert USE_CCACHE=yes (keeps PRIVATE_CCACHE=yes, still read by compile_prepare_vars__ccache for CCACHE_DIR). Without this, ENABLE_EXTENSIONS=ccache-remote on its own would no longer wire up the ccache binary after the refactor.

User-visible behavior

USE_CCACHE=yes / PRIVATE_CCACHE=yes no longer auto-enable the ccache extension — use ENABLE_EXTENSIONS=ccache (or EXT=ccache) explicitly. Builds that still set them without an active compile-cache extension get a migration warning (USE_CCACHE / PRIVATE_CCACHE are ignored). USE_CCACHE=no (the default) is unchanged.

Test plan

Built on a fresh DigitalOcean cloud builder (AMD EPYC 8c, Ubuntu 24.04), BOARD=helios64 BRANCH=edge:

# Configuration Runtime Marker
1 ENABLE_EXTENSIONS=ccache kernel cold 77:45 min Ccache result hit=12 miss=14410
2 USE_CCACHE=no kernel 55:54 min no ccache markers (as expected)
3 ENABLE_EXTENSIONS=ccache uboot+ATF cold 2:11 min Ccache result hit=8 miss=1002
4 ENABLE_EXTENSIONS=ccache-remote + CCACHE_REMOTE_STORAGE=http://m1:8088/ccache/ over WireGuard interrupted (~5 min of compile) Remote ccache result hit=4536 miss=2791 write=2740 err=0 (61%)

Logs: paste.armbian.com/{enaretezuc,noxayoyoni,vonuyajido}.

Summary by CodeRabbit

  • New Features

    • Extensible compile-wrapper that reliably runs pre/post build hooks (including on interruption).
    • ccache compile-cache backend with shared/private modes, configurable cache directory, pre/post-build reporting, hit-rate display, and umask preservation in minimal environments.
  • Refactor

    • Compile-cache setup delegated to the extension system and integrated into ATF/Crust/kernel/uboot build flows; legacy post-build reporting preserved.
  • Chores

    • Normalized extension-list handling for per-extension mutex checks.

Summary by CodeRabbit

  • New Features

    • Added a new compile-cache backend extension for ccache, including configurable cache directory handling, optional verbose stats output, and improved hit-rate reporting during builds.
    • Introduced pre-/post-compilation hooks for extensions, enabling cache-related behavior across build steps.
  • Refactor

    • Updated kernel and U-Boot compilation to use the new compilation wrapper (with hooks) instead of the prior built-in ccache statistics flow.
    • Adjusted ATF and Crust build environment wiring to use the wrapper-style CCACHE substitution.
    • Compile-cache setup is now extension-driven (legacy USE_CCACHE-style variables may be ignored); ccache-remote now explicitly enables the ccache backend and preserves shared cache directory pinning.

@iav iav requested review from a team and igorpecovnik as code owners May 17, 2026 01:29
@iav iav requested review from Tearran and removed request for a team May 17, 2026 01:29
@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf84efed-ae4c-4b60-b7e2-2c1b0f3714b4

📥 Commits

Reviewing files that changed from the base of the PR and between f7db554 and 6139882.

📒 Files selected for processing (12)
  • extensions/ccache-remote/ccache-remote.sh
  • extensions/ccache.sh
  • lib/functions/compilation/atf.sh
  • lib/functions/compilation/ccache.sh
  • lib/functions/compilation/compile-wrapper.sh
  • lib/functions/compilation/crust.sh
  • lib/functions/compilation/kernel.sh
  • lib/functions/compilation/uboot.sh
  • lib/functions/configuration/compilation-config.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/general/extensions.sh
  • lib/library-functions.sh
💤 Files with no reviewable changes (1)
  • lib/functions/compilation/ccache.sh
✅ Files skipped from review due to trivial changes (1)
  • lib/functions/configuration/main-config.sh
🚧 Files skipped from review as they are similar to previous changes (10)
  • lib/functions/compilation/crust.sh
  • lib/functions/compilation/uboot.sh
  • extensions/ccache-remote/ccache-remote.sh
  • lib/functions/compilation/atf.sh
  • lib/library-functions.sh
  • lib/functions/compilation/kernel.sh
  • lib/functions/configuration/compilation-config.sh
  • lib/functions/compilation/compile-wrapper.sh
  • lib/functions/general/extensions.sh
  • extensions/ccache.sh

📝 Walkthrough

Walkthrough

Introduce a generic compile-wrapper framework, implement ccache as an extension with config validation and pre/post hooks, move compile-cache setup to extension initialization, update ATF/Crust/kernel/uboot build flows to use the new wrapper, and wire ccache-remote to auto-enable the ccache backend.

Changes

Compilation Wrapper Refactoring

Layer / File(s) Summary
Generic Backend-Agnostic Wrapper Framework
lib/functions/compilation/compile-wrapper.sh, lib/library-functions.sh
Adds do_with_compile_wrapper and a guaranteed cleanup-invoked post-hook; library aggregation now sources the wrapper instead of the old ccache stats helper.
Configuration & Extension List Helper
lib/functions/general/extensions.sh, lib/functions/configuration/compilation-config.sh, lib/functions/configuration/main-config.sh
Moves inline ccache initialization out of prepare_compilation_vars and into an extension hook; adds extension_list_normalized() for canonical extension list derivation; applies whitespace and comment alignment tweaks.
Compilation Targets & Make-config Hooks
lib/functions/compilation/atf.sh, lib/functions/compilation/crust.sh, lib/functions/compilation/kernel.sh, lib/functions/compilation/uboot.sh
Kernel and U-Boot builds use do_with_compile_wrapper; ATF and Crust gain *_make_config hooks and conditionally prepend ${CCACHE} into CROSS_COMPILE/CC when set.
ccache Extension Module
extensions/ccache.sh
Implements ccache as an extension: extension_prepare_config__ccache conflict check, compile_prepare_vars__ccache (exports CCACHE, adjusts PATH, sets CCACHE_DIR/CCACHE_UMASK), UMASK injection into make env arrays, compile_wrapper_pre__ccache/compile_wrapper_post__ccache for stats and size reporting, and helpers ccache_get_stat() and ccache_hit_pct().
ccache-remote Integration
extensions/ccache-remote/ccache-remote.sh
Auto-enables the ccache backend extension and updates cache-directory documentation to emphasize PRIVATE_CCACHE=yes instead of the now-removed USE_CCACHE flag.

Sequence Diagram

sequenceDiagram
  participant Build as BuildTarget
  participant Wrapper as do_with_compile_wrapper
  participant PreExt as compile_wrapper_pre__ccache
  participant Make as make
  participant PostExt as compile_wrapper_post__ccache
  Build->>Wrapper: start build under wrapper
  Wrapper->>Wrapper: register post-hook cleanup
  Wrapper->>PreExt: call_extension_method compile_wrapper_pre
  PreExt->>PreExt: clear stats, record cache dir/size
  Wrapper->>Make: run make (compiler wrapped by CCACHE)
  Make->>Make: compile
  Wrapper->>PostExt: explicit post-hook call
  PostExt->>PostExt: parse stats, compute hit%, report
  Wrapper->>Build: return exit code
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hop through scripts with a careful shim,
I make a wrapper generic, neat and trim,
Ccache now lives out in its own small nest,
Pre and post hooks tally; they do their best,
Builders hum along — the cache does the rest.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: refactoring ccache support from core compilation into a swappable extension framework, which is the primary objective of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added 05 Milestone: Second quarter release size/large PR with 250 lines or more Needs review Seeking for review Framework Framework components labels May 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@extensions/ccache.sh`:
- Around line 109-117: When SHOW_CCACHE is enabled, guard the probes that
compute sizes by validating __ext_ccache_dir_actual before running du and
numfmt: ensure __ext_ccache_dir_actual is non-empty and a directory (e.g., test
-n and -d) and only then set __ext_ccache_dir_size_before and compute
ccache_dir_size_before_human; otherwise set __ext_ccache_dir_size_before to a
safe default (0) and ccache_dir_size_before_human to a fallback like "unset" or
"N/A". Update the logic around __ext_ccache_dir_size_before, the du call, and
the numfmt call so they are conditional on the existence check to keep the
post-hook best-effort and avoid aborting on empty/invalid
__ext_ccache_dir_actual.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f98c058c-d6d2-44e4-be35-f0577a0cfeeb

📥 Commits

Reviewing files that changed from the base of the PR and between be62dc5 and f32ac58.

📒 Files selected for processing (11)
  • extensions/ccache.sh
  • lib/functions/compilation/atf.sh
  • lib/functions/compilation/ccache.sh
  • lib/functions/compilation/compile-wrapper.sh
  • lib/functions/compilation/crust.sh
  • lib/functions/compilation/kernel.sh
  • lib/functions/compilation/uboot.sh
  • lib/functions/configuration/compilation-config.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/general/extensions.sh
  • lib/library-functions.sh
💤 Files with no reviewable changes (1)
  • lib/functions/compilation/ccache.sh

Comment thread extensions/ccache.sh Outdated
@iav iav force-pushed the refactor/ccache-as-extension branch from f32ac58 to f1138ac Compare May 17, 2026 01:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/library-functions.sh (1)

288-300: ⚡ Quick win

Remove duplicate compile-wrapper.sh sourcing.

Line 288-Line 290 and Line 297-Line 299 source the same file twice. Please keep a single inclusion to avoid duplicate top-level execution and keep the generated aggregation deterministic.

Proposed fix
-# no errors tolerated. invoked before each sourced file to make sure.
-#set -o pipefail  # trace ERR through pipes - will be enabled "soon"
-#set -o nounset   ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
-set -o errtrace # trace ERR through - enabled
-set -o errexit  ## set -e : exit the script if any statement returns a non-true return value - enabled
-### lib/functions/compilation/compile-wrapper.sh
-# shellcheck source=lib/functions/compilation/compile-wrapper.sh
-source "${SRC}"/lib/functions/compilation/compile-wrapper.sh
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/library-functions.sh` around lines 288 - 300, Remove the duplicate
sourcing of compile-wrapper.sh: locate the two identical source statements
referencing source "${SRC}"/lib/functions/compilation/compile-wrapper.sh (the
top-level include around the set -o errtrace/errexit block) and delete one of
them so the file is only sourced once; ensure the remaining block preserves the
intended shell options (set -o errtrace and set -o errexit) and any comments,
leaving a single source line for compile-wrapper.sh to avoid duplicate
execution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lib/library-functions.sh`:
- Around line 288-300: Remove the duplicate sourcing of compile-wrapper.sh:
locate the two identical source statements referencing source
"${SRC}"/lib/functions/compilation/compile-wrapper.sh (the top-level include
around the set -o errtrace/errexit block) and delete one of them so the file is
only sourced once; ensure the remaining block preserves the intended shell
options (set -o errtrace and set -o errexit) and any comments, leaving a single
source line for compile-wrapper.sh to avoid duplicate execution.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 57a7c283-8c3e-43ed-9f3f-5ecb69277112

📥 Commits

Reviewing files that changed from the base of the PR and between f32ac58 and f1138ac.

📒 Files selected for processing (8)
  • extensions/ccache.sh
  • lib/functions/compilation/ccache.sh
  • lib/functions/compilation/kernel.sh
  • lib/functions/compilation/uboot.sh
  • lib/functions/configuration/compilation-config.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/general/extensions.sh
  • lib/library-functions.sh
💤 Files with no reviewable changes (1)
  • lib/functions/compilation/ccache.sh
🚧 Files skipped from review as they are similar to previous changes (5)
  • lib/functions/compilation/uboot.sh
  • lib/functions/general/extensions.sh
  • lib/functions/compilation/kernel.sh
  • extensions/ccache.sh
  • lib/functions/configuration/compilation-config.sh

@iav iav force-pushed the refactor/ccache-as-extension branch 3 times, most recently from d3170e8 to 6dd6a7c Compare May 17, 2026 20:21
@iav iav force-pushed the refactor/ccache-as-extension branch from 6dd6a7c to 6645b8f Compare May 19, 2026 23:06
@igorpecovnik

Copy link
Copy Markdown
Member

USE_CCACHE=yes in userpatches/lib.config does not auto-enable the ccache extension. lib.config is sourced after initialize_extension_manager

How safe is moving lib.config reading higher in the chain?

@iav

iav commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

@igorpecovnik dug into the origin of this: the lib.config warning I added in one of the codex rounds was a guard against a theoretical edge case, not an observed pattern. I have no evidence that anyone actually sets USE_CCACHE=yes (or anything else, really) in userpatches/lib.config. And the @TODO this is _very legacy_ and should be removed comment in main-config.sh was placed by @rpardini back on 2023-04-13 (ac25ac18b) — three years standing, nobody's ripped it out, and no in-tree consumers ever appeared.

Three options, in increasing aggressiveness:

  1. Drop my noise only: pull the three blocks I added in this PR (the prepare_compilation_vars warning, the comments in main-config.sh and the extensions/ccache.sh header). Leave lib.config lifecycle exactly as it is — a separate story.
  2. Move the sourcing block above initialize_extension_manager: restores the pre-hook semantics (plain variable overrides). Can land as a separate commit in this PR, or as a follow-up.
  3. Remove lib.config support entirely: delete the sourcing block as the in-tree TODO has been requesting for three years. If anything out-of-tree breaks, it's a one-time adoption cost; nobody returns to the topic after that.

@iav iav force-pushed the refactor/ccache-as-extension branch from 6645b8f to b7c3436 Compare May 21, 2026 20:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/functions/compilation/crust.sh (1)

63-69: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Guard $CCACHE expansion to prevent leading space in CROSS_COMPILE when cache is disabled.

Same issue as ATF (see comment on atf.sh:96-99): when CCACHE is empty, the unguarded expansion "CROSS_COMPILE='$CCACHE $CRUST_COMPILER'" produces a leading space that breaks the compiler invocation.

Apply the same conditional-suffix fix to both make invocations (lines 65 and 69).

🔧 Proposed fix
 	run_host_command_logged CCACHE_BASEDIR="$(pwd)" \
 		"CFLAGS='-fdiagnostics-color=always -Wno-error=attributes -Wno-error=incompatible-pointer-types'" \
-		make ${CRUSTCONFIG} "${CTHREADS}" "CROSS_COMPILE='$CCACHE $CRUST_COMPILER'"
+		make ${CRUSTCONFIG} "${CTHREADS}" "CROSS_COMPILE='${CCACHE:+$CCACHE }$CRUST_COMPILER'"

 	run_host_command_logged CCACHE_BASEDIR="$(pwd)" \
 		"CFLAGS='-fdiagnostics-color=always -Wno-error=attributes -Wno-error=incompatible-pointer-types'" \
-		make $target_make "${CTHREADS}" "CROSS_COMPILE='$CCACHE $CRUST_COMPILER'"
+		make $target_make "${CTHREADS}" "CROSS_COMPILE='${CCACHE:+$CCACHE }$CRUST_COMPILER'"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/functions/compilation/crust.sh` around lines 63 - 69, The CROSS_COMPILE
argument currently unconditionally expands CCACHE causing a leading space when
CCACHE is empty; update both calls to run_host_command_logged that build with
"CROSS_COMPILE='$CCACHE $CRUST_COMPILER'" to guard the cache token (e.g. use a
conditional expansion so the space only appears when CCACHE is non-empty),
making the string effectively "CROSS_COMPILE='${CCACHE:+$CCACHE
}$CRUST_COMPILER'"; adjust both occurrences around the make invocations (the
lines using run_host_command_logged, CROSS_COMPILE, CCACHE and CRUST_COMPILER)
so the compiler invocation is not broken when CCACHE is disabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/functions/compilation/atf.sh`:
- Around line 96-99: The CROSS_COMPILE assignment can get a leading space when
CCACHE is empty; in the run_host_command_logged call where
CROSS_COMPILE='${CCACHE} ${ATF_COMPILER}' and CC='${CCACHE} ${ATF_COMPILER}gcc',
change the expansions to use conditional parameter expansion so the space is
only inserted when CCACHE is non-empty (e.g., use the ${CCACHE:+...} form around
the space and CCACHE) so both CROSS_COMPILE and CC are constructed correctly;
update the two occurrences inside the run_host_command_logged invocation
(referencing CROSS_COMPILE, CC, CCACHE, ATF_COMPILER) accordingly.

---

Outside diff comments:
In `@lib/functions/compilation/crust.sh`:
- Around line 63-69: The CROSS_COMPILE argument currently unconditionally
expands CCACHE causing a leading space when CCACHE is empty; update both calls
to run_host_command_logged that build with "CROSS_COMPILE='$CCACHE
$CRUST_COMPILER'" to guard the cache token (e.g. use a conditional expansion so
the space only appears when CCACHE is non-empty), making the string effectively
"CROSS_COMPILE='${CCACHE:+$CCACHE }$CRUST_COMPILER'"; adjust both occurrences
around the make invocations (the lines using run_host_command_logged,
CROSS_COMPILE, CCACHE and CRUST_COMPILER) so the compiler invocation is not
broken when CCACHE is disabled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d6fb8ea0-443c-4249-83f7-ef62086bbfc8

📥 Commits

Reviewing files that changed from the base of the PR and between 6645b8f and b7c3436.

📒 Files selected for processing (11)
  • extensions/ccache.sh
  • lib/functions/compilation/atf.sh
  • lib/functions/compilation/ccache.sh
  • lib/functions/compilation/compile-wrapper.sh
  • lib/functions/compilation/crust.sh
  • lib/functions/compilation/kernel.sh
  • lib/functions/compilation/uboot.sh
  • lib/functions/configuration/compilation-config.sh
  • lib/functions/configuration/main-config.sh
  • lib/functions/general/extensions.sh
  • lib/library-functions.sh
💤 Files with no reviewable changes (1)
  • lib/functions/compilation/ccache.sh

Comment thread lib/functions/compilation/atf.sh Outdated
@iav iav force-pushed the refactor/ccache-as-extension branch from e2e5eba to 4032a46 Compare May 21, 2026 21:19
@iav iav changed the title refactor(compilation): extract ccache into a swappable extension refactor(compilation): extract ccache support into a swappable extension May 26, 2026
@iav iav force-pushed the refactor/ccache-as-extension branch from 4032a46 to 8f3a8a6 Compare June 8, 2026 20:53
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@EvilOlaf

EvilOlaf commented Jun 9, 2026

Copy link
Copy Markdown
Member

userpatches/lib.config

Isn't this file marked as deprecated for years?

@iav

iav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@igorpecovnik @EvilOlaf I wasn't sure either. Then maybe I should just drop everything related to lib.config from this PR — both the warning and the doc note — rather than reorder the source chain?

@iav

iav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a fixup on top: removes the USE_CCACHE/PRIVATE_CCACHE auto-enable shim from main-config.sh and the lib.config fallback warning from compilation-config.sh. To enable ccache, use ENABLE_EXTENSIONS=ccache explicitly. Squash-ready once approved.

@igorpecovnik

igorpecovnik commented Jun 9, 2026

Copy link
Copy Markdown
Member

In light of this ... how to solve this problem - we have several github runners and after recent datacenter deployment, it gets handy (it is necessary) to make use of locally stored ccache (redis), Git cache, apt-cacher and OCI registry cache. Now how to drive this efficiently? Several TB is not a problem. We insert general config for build type (images) https://github.com/armbian/os/blob/main/userpatches/config-armbian-images.conf but we also need variables per location - to define which (local) cache servers are in use. Recently we are getting a lot of timeouts from ghcr and in general its very slow.

@iav

iav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

@igorpecovnik A few clarifying questions before suggesting anything:

  1. What's the gap in the current file-based approach — is it the per-location wiring itself, or something about how the framework exposes the variables?
  2. Are the cache servers (Redis, apt-cacher, OCI registry) reachable from the runners directly — i.e., are they external services in your datacenter, not co-located on the runner itself?
  3. If external servers are reachable, would service discovery (DNS SRV records or mDNS/Avahi) be viable in your setup, or are you constrained to static addresses in config files?
  4. Where would configuration be most convenient to maintain — files on the runners, environment variables in GitHub Actions secrets/variables (per repo or org), or something else? I'm not immediately sure what would be the least friction in your setup.

@igorpecovnik

igorpecovnik commented Jun 9, 2026

Copy link
Copy Markdown
Member
  1. Currently its nothing per location and no caching is used.
  2. Cache servers are on a dedicated machine (plenty of storage and memory) connected with runners via dual 10Gbps LAN. But it would also help running cache servers on a single machine that runs multiple runners.
  3. Local DNS is operational.
  4. Good question. Currently we have servers and runners data stored in Netbox db. We could maintain data there and cache JSON export to https://github.armbian.com/ from where CI would pick it up and make use of.

@iav

iav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Makes sense to start simple: put the needed variables (CCACHE_REMOTE_STORAGE, apt proxy, OCI mirror URL, etc.) into the Netbox JSON export, have each runner fetch and apply them before calling ./compile.sh. The framework extensions already read from env — no changes needed on that side. Then see what friction actually appears in practice before adding more machinery.

@iav

iav commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Added a migration warning on top of the fixup: if USE_CCACHE=yes or PRIVATE_CCACHE=yes is set, a wrn-level alert now fires at build time directing users to ENABLE_EXTENSIONS=ccache (or another backend). Comment in code marks it for removal after mid-2027.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/functions/configuration/compilation-config.sh`:
- Around line 33-39: The warning is emitted whenever USE_CCACHE or
PRIVATE_CCACHE are set even if an extension already initialized compile-cache
state; change the condition so display_alert only runs when the legacy vars are
set AND no compile-cache backend has been prepared (e.g., check a flag set by
extensions such as COMPILE_CACHE_PREPARED or COMPILE_CACHE_INITIALIZED, or test
whether compile_prepare_vars has run), leaving ENABLE_EXTENSIONS logic untouched
and still advising to use ENABLE_EXTENSIONS=ccache when no backend is
initialized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f755972-36c1-4a30-a9f9-2e24c29bcab2

📥 Commits

Reviewing files that changed from the base of the PR and between 5f3958c and 413694a.

📒 Files selected for processing (1)
  • lib/functions/configuration/compilation-config.sh

Comment thread lib/functions/configuration/compilation-config.sh
@iav iav force-pushed the refactor/ccache-as-extension branch 2 times, most recently from d5cee5f to 8ec51b3 Compare June 10, 2026 16:58
iav added 8 commits June 14, 2026 14:29
The variable has been declared but never assigned or used since
8278dc5 (2023-06-20, 'allwinner: Enable crust compilation'), which
copy-pasted the binutils_version + binutils_flags skeleton from atf.sh
but did not bring along the gcc/ld probe block that conditionally
populates the flag, nor the TF_LDFLAGS-style use site. Crust is or1k-elf
firmware where --no-warn-rwx-segment is not relevant, so the absence
of the probe is by design; the leftover empty declaration is just dead.

Removes a pre-existing SC2034 'appears unused' warning that surfaced
when the file is touched by other refactors.

Assisted-by: Claude:claude-opus-4.7
CROSS_COMPILE and CC were hard-coded to 'ccache' which:
  - breaks when USE_CCACHE=no (CCACHE='' but 'ccache' still tried)
  - prevents wrapper substitution by extensions (sccache, distcc)

Match the established kernel/uboot convention where the cache wrapper
is parameterised via ${CCACHE} (set by configure-ccache based on
USE_CCACHE). Default value '' means no wrapper.

Assisted-by: Claude:claude-opus-4.7
…le_wrapper

Adds three new extension points to the compilation pipeline:

  - atf_make_config: called right before invoking 'make' for ATF (TF-A).
    Receives env that will be passed to make; extensions can mutate
    CCACHE / CC / CROSS_COMPILE to inject wrappers.
  - crust_make_config: same for the or1k Crust firmware (defconfig +
    target make).
  - do_with_compile_wrapper / compile_wrapper_pre / compile_wrapper_post:
    high-level wrapper that bookends an arbitrary compilation block
    with pre/post hooks. Lets extensions observe a compile pass
    end-to-end (clear stats / dump stats / mount caches / etc) without
    having to patch each artifact's compile.sh.

Pure addition: no existing call site is wired yet (kernel/uboot
migration follows in subsequent commits). The hooks are no-ops until
an extension implements them.

Assisted-by: Claude:claude-opus-4.7
Extracts ccache-specific logic from lib/functions/compilation/ccache.sh
into a new opt-out extension extensions/ccache.sh. The extension wires
itself into the compilation pipeline through the new hook points:

  - compile_prepare_vars: dispatched from prepare_compilation_vars
    (early). Computes CCACHE / CCACHE_DIR / CCACHE_UMASK / PATH and
    exports them so subsequent make-quoted-params arrays expand
    correctly. Runs before any artifact's make invocation.
  - compile_wrapper_pre/_post: zeros / reports per-build stats around
    each artifact's compile pass.
  - {kernel,uboot,atf,crust}_make_config: ensures CCACHE_DIR /
    CCACHE_UMASK are visible to the make subshell on each artifact.

This is an additive change: nothing yet calls call_extension_method
"compile_prepare_vars" — that wiring lands in the next refactor commit.

Assisted-by: Claude:claude-opus-4.7
…che.sh

Wires the new ccache extension (extensions/ccache.sh) into the
compilation pipeline, replacing the in-core lib/functions/compilation/
ccache.sh module that was sourced unconditionally.

Changes:
  - lib/functions/compilation/kernel.sh, uboot.sh: wrap the compile
    pass with do_with_compile_wrapper so the new compile_wrapper_pre/
    _post hooks fire around it.
  - lib/functions/configuration/compilation-config.sh: dispatch
    compile_prepare_vars (early phase, before any make-quoted-params
    array is built) instead of inlining configure-ccache. Also clears
    stale CCACHE export from a previous artifact iteration so a
    second uboot/kernel call in the same shell can't reuse a now-
    disabled cache. Keeps a one-shot deprecation warning if any
    user-patch still sources the legacy lib.config.
  - lib/functions/configuration/main-config.sh: if USE_CCACHE=yes
    (or the ccache-remote extension is enabled) auto-enable the
    'ccache' extension before initialize_extension_manager runs.
    Honours both EXT alias and the legacy space-separated
    ENABLE_EXTENSIONS form.
  - lib/functions/general/extensions.sh: add extension_list_normalized
    helper used by the auto-enable shim and per-extension mutex
    checks. It (a) normalises all IFS whitespace (space, tab,
    newline) — matching what initialize_extension_manager splits on
    — and (b) folds in extensions enabled programmatically via
    enable_extension() (from board/family/user configuration) by
    scanning extension_function_info. Without this fold-in, a board
    that does `enable_extension ccache-remote` would slip past both
    the auto-enable shim and the mutex guard, leaving USE_CCACHE=yes
    with no backend hook (or letting two compile-cache backends
    coexist).
  - lib/functions/compilation/ccache.sh: removed (logic moved to
    extensions/ccache.sh).

Behaviour is preserved for USE_CCACHE=yes (default-on for kernel/uboot
builds) and USE_CCACHE=no callers. ENABLE_EXTENSIONS=ccache-remote
implicitly pulls in ccache, matching pre-refactor coupling.

Assisted-by: Claude:claude-opus-4.7
…ding space

When USE_CCACHE=no, CCACHE is set to "" by compilation-config.sh.
The make-argument pattern "CROSS_COMPILE='${CCACHE} ${COMPILER}'" then
expands to "CROSS_COMPILE=' arm-…-'" (literal leading space). make
in turn evaluates ${CROSS_COMPILE}gcc as " arm-…-gcc" with that
leading space and fails to exec.

Switch to "${CCACHE:+${CCACHE} }${COMPILER}" so the trailing space is
only inserted when CCACHE is non-empty. Matches the idiom already used
in lib/functions/compilation/uboot.sh:259.

- atf.sh:96 — regression introduced earlier in this PR by the
  "use ${CCACHE} variable instead of hardcoded ccache" commit; the
  previous hardcoded ccache was always non-empty so the latent issue
  was masked.
- crust.sh:65,69 — pre-existing in main, same fix applied since the
  pattern is identical.

Assisted-by: Claude:claude-opus-4.7
Since the ccache refactor (extension-based backends), USE_CCACHE no longer
activates a backend on its own — only the ccache extension wires up the
binary. ccache-remote set USE_CCACHE=yes but never enabled that extension,
so ENABLE_EXTENSIONS=ccache-remote alone would leave ${CCACHE} empty and
remote storage with nothing to read/write.

Add a top-level enable_extension "ccache" so ccache-remote pulls in the
backend it layers on top of, and drop the now-inert USE_CCACHE=yes (keeping
PRIVATE_CCACHE=yes, still read by compile_prepare_vars__ccache for CCACHE_DIR).

Assisted-by: Claude:claude-opus-4.8
@iav iav force-pushed the refactor/ccache-as-extension branch from f7db554 to 6139882 Compare June 14, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

05 Milestone: Second quarter release Framework Framework components Needs review Seeking for review size/large PR with 250 lines or more

Development

Successfully merging this pull request may close these issues.

3 participants