Skip to content

build: fix mac CI ccache, only wrap darwin CC/CXX in env -u when include paths are set - #7540

Open
PastaPastaPasta wants to merge 2 commits into
dashpay:developfrom
PastaPastaPasta:fix-darwin-ccache-env-prefix
Open

build: fix mac CI ccache, only wrap darwin CC/CXX in env -u when include paths are set#7540
PastaPastaPasta wants to merge 2 commits into
dashpay:developfrom
PastaPastaPasta:fix-darwin-ccache-env-prefix

Conversation

@PastaPastaPasta

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

ccache is silently disabled for the entire mac-build CI job, and has been since d201e43 (2026-01-19) re-added the env -u prefix to darwin_CC/darwin_CXX (it was previously broken from 2020-08 until the bitcoin#30451 backport in 1d8868b removed the prefix in 2025-02).

Every mac CI run shows:

Cacheable calls:      0 / 1021 ( 0.00%)
Uncacheable calls: 1021 / 1021 (100.0%)

and recompiles all objects from scratch (~22 min compile in run 30848679596), while saving a 17 KB ccache cache entry.

Root cause: configure prepends ccache to CC, producing ccache env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH /usr/bin/clang .... ccache treats env as the compiler (type other), consumes -u VAR as an option taking an argument, then classifies the absolute clang path — an existing file not starting with - — as a second source file. CCACHE_DEBUG shows the verdict:

Compiler: /usr/bin/env
Compiler type: other
Result: multiple_source_files

Every call is rejected and silently falls back to the real compiler, so the build succeeds and nothing ever flagged it. Current ccache master has the same parsing behavior; this is not fixed by upgrading ccache.

What was done?

The env -u prefix exists to stop Guix (contrib/guix/libexec/build.sh exports C_INCLUDE_PATH="${NATIVE_GCC}/include" etc.) from leaking native-toolchain headers into the darwin cross-build — the conflict d201e43 fixed. CI never sets those variables, so the prefix does nothing there except break ccache.

The prefix is now emitted only when C_INCLUDE_PATH or CPLUS_INCLUDE_PATH is actually defined (checked via $(origin ...), so set-but-empty still counts as set):

  • Guix: variables are exported → prefix present → behavior unchanged (Guix doesn't use ccache, so the ccache issue never applied there).
  • CI / containers: variables unset → plain $(clang_prog) → ccache wraps clang directly and caching works.

Upstream removed the prefix entirely (bitcoin#30451) because their Guix build.sh no longer exports these variables; ours still does, so the conditional keeps the Guix protection while re-applying the effect of bitcoin#30451 everywhere else. The stale TODO comments pointing at bitcoin#30451/#7184 are replaced with an explanation of both constraints.

Cached depends are not invalidated by this change: depends/gen_id hashes compiler -v output, which is byte-identical with and without the prefix when the variables are unset (verified below).

How Has This Been Tested?

All in ubuntu:24.04 (same ccache 4.9.1 + clang 18 as the CI image), plus a make-level check:

  1. Repro of the bug: ccache env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH /usr/bin/clang --target=x86_64-apple-darwin -isysroot... -nostdlibinc ... -c t.cUncacheable calls: 1/1, CCACHE_DEBUG log shows Result: multiple_source_files. Bare clang instead of an absolute path does not trigger it, confirming the source-file misparse.
  2. New shape: same flags without the prefix → Cacheable calls: 2/2, second compile is a cache hit.
  3. Conditional: scratch makefile including depends/hosts/darwin.mk: with both variables unset darwin_CC has no prefix; with C_INCLUDE_PATH set (or set-but-empty) the prefix is emitted.
  4. depends build id stability: {clang -v; clang -v -E -xc -o /dev/null -} output (the gen_id preimage components) is byte-identical with and without the env -u prefix when the variables are unset, so CI's cached depends remain valid.

Guix builds are unaffected by construction (the conditional evaluates true in that environment), but a guix-build run on this PR will confirm.

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

The unconditional 'env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH' prefix on darwin_CC/darwin_CXX silently disables ccache for every macOS cross-compile in CI: configure prepends ccache to CC, producing 'ccache env -u VAR /path/to/clang ...'. ccache treats 'env' as the compiler (type 'other'), consumes '-u VAR' as an option taking an argument, and then classifies the absolute clang path -- an existing file not starting with '-' -- as a second source file. Every compile is rejected as 'multiple_source_files' and falls back to the real compiler, so the mac CI job recompiles all ~1000 objects from scratch (~22 min) on every run while saving a 17 KB ccache cache entry.

The prefix exists to stop Guix (contrib/guix/libexec/build.sh) from leaking native-GCC include paths into the darwin cross-build. CI never sets those variables, so emit the prefix only when C_INCLUDE_PATH or CPLUS_INCLUDE_PATH is actually defined: Guix behavior is unchanged (variables set, and Guix does not use ccache), and CI gets a working mac ccache. depends build ids are unaffected in CI because gen_id hashes compiler -v output, which is byte-identical with and without the prefix when the variables are unset.
@PastaPastaPasta PastaPastaPasta added this to the 24 milestone Aug 4, 2026
@thepastaclaw

thepastaclaw commented Aug 4, 2026

Copy link
Copy Markdown

🕓 Ready for review — 17 ahead in queue (commit 1dc8e9b)
Queue position: 18/18 · 2 reviews active
ETA: start ~20:07 UTC · complete ~20:31 UTC (median 23m across 30 recent reviews; 2 slots)
Queued 45m ago · Last checked: 2026-08-04 16:40 UTC

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c6d1d18f-c072-466c-bc96-7f397412d1a3

📥 Commits

Reviewing files that changed from the base of the PR and between 477e5a7 and 1dc8e9b.

📒 Files selected for processing (1)
  • depends/hosts/darwin.mk
🚧 Files skipped from review as they are similar to previous changes (1)
  • depends/hosts/darwin.mk

Walkthrough

The Darwin host configuration adds a conditional darwin_env_unset prefix. The prefix unsets C_INCLUDE_PATH and CPLUS_INCLUDE_PATH only when either variable is defined. Both darwin_CC and darwin_CXX use this prefix. The previous unconditional prefix and related TODO comments were removed.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: udjinm6

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: conditionally applying the env -u prefix to darwin CC/CXX only when include paths are set, which fixes ccache in macOS CI.
Description check ✅ Passed The description is directly related to the changeset, providing detailed context about the ccache breakage, root cause analysis, the fix implementation, and testing performed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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.

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

I don't fully follow this one; but ccache for Mac builds have been broken since Jan, we should probably fix that :) this is fable's proposal.

@PastaPastaPasta

Copy link
Copy Markdown
Member Author

Much better

ccache version 4.9.1
Cacheable calls:   1009 / 1021 (98.82%)
  Hits:              65 / 1009 ( 6.44%)
    Direct:          62 /   65 (95.38%)
    Preprocessed:     3 /   65 ( 4.62%)
  Misses:           944 / 1009 (93.56%)
Uncacheable calls:   12 / 1021 ( 1.18%)
Local storage:
  Cache size (GB):  0.3 /  0.6 (47.81%)
  Hits:              65 / 1009 ( 6.44%)
  Misses:           944 / 1009 (93.56%)
Original data:         1.1 GB
Old compressed data: 286.9 MB (25.4% of original size)
  Compression ratio: 3.941 x  (74.6% space savings)
New compressed data: 249.4 MB (22.1% of original size)
  Compression ratio: 4.533 x  (77.9% space savings)
Size change:         -37.5 MB

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Final validation — Codex + Sonnet

The change correctly applies the Darwin compiler environment wrapper only when either include-path variable is defined, preserving Guix header isolation while allowing ccache to invoke clang directly in CI. The implementation is narrowly scoped, handles unset, set, and set-but-empty variables correctly, and introduces no actionable defects.

Source: reviewers gpt-5.6-sol (general, dash-core-commit-history) and claude-sonnet-5 (general, dash-core-commit-history); final verifier gpt-5.6-sol (fallback after two unparseable claude-sonnet-5 verifier attempts).

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (completed), gpt-5.6-sol — dash-core-commit-history (completed)
  • Verifier: gpt-5.6-sol — final-verifier (fallback)
  • Sonnet reviewers: claude-sonnet-5 — general (failed), claude-sonnet-5 — dash-core-commit-history (completed), claude-sonnet-5 — general (completed)

@PastaPastaPasta
PastaPastaPasta requested review from UdjinM6 and knst August 4, 2026 13:36
Comment thread depends/hosts/darwin.mk
# TODO: remove C_INCLUDE_PATH when it is indeed useless
# https://github.com/bitcoin/bitcoin/pull/30451 has been partiall reverted in #7184 and should be re-applied
darwin_CC=env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH $(clang_prog) --target=$(host) \
# C_INCLUDE_PATH/CPLUS_INCLUDE_PATH leak native-toolchain headers into the

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

keep TODO; bitcoin#30451 has been done partially and this workaround should be removed when 30451 is fully backported.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1dc8e9b396

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread depends/hosts/darwin.mk
Comment on lines +70 to +71
ifneq ($(origin C_INCLUDE_PATH) $(origin CPLUS_INCLUDE_PATH),undefined undefined)
darwin_env_unset=env -u C_INCLUDE_PATH -u CPLUS_INCLUDE_PATH

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Invalidate the depends workflow cache for this host change

In the checked .github/workflows/build-depends.yml, PACKAGES_HASH includes only depends/packages/* and depends/Makefile (:78), so this change leaves the exact mac depends cache key unchanged and causes the producer job to be skipped. However, depends/funcs.mk:43-45 hashes hosts/darwin.mk into every package recipe ID, so the source consumer restores only old-ID package archives and rebuilds the entire mac dependency tree; because that consumer does not save the depends cache, this repeats on every mac run. Include the host file in the workflow cache key or otherwise force the producer to refresh the cache.

AGENTS.md reference: AGENTS.md:L195-L197

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants