Skip to content

Fix ccache never being invoked on iOS builds - #58066

Open
janicduplessis wants to merge 1 commit into
react:mainfrom
janicduplessis:ccache-resolve-binary-without-build-setting
Open

Fix ccache never being invoked on iOS builds#58066
janicduplessis wants to merge 1 commit into
react:mainfrom
janicduplessis:ccache-resolve-binary-without-build-setting

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary:

ccache is never invoked on iOS builds, even with USE_CCACHE=1.

set_ccache_compiler_and_linker_build_settings points CC/CXX at ccache-clang.sh and passes the resolved path alongside as a build setting, which the script reads as an environment variable:

exec $CCACHE_BINARY clang "$@"

Xcode does not export build settings into the environment of a compile task, so CCACHE_BINARY is empty during a build and that line word-splits down to exec clang "$@". The build succeeds and looks normal, so it fails silently: you get plain clang plus a shell fork per translation unit, which is slower than leaving ccache off. Logging the variable from inside the launcher during a clean rn-tester build printed an empty value on all 1578 compiler invocations, with 0 cacheable calls.

pod install now generates the launchers into Pods/ with both paths resolved at install time, and points CC/CXX at those. The generated script is the one this removes, with $CCACHE_BINARY replaced by the resolved ccache path and the config path absolute rather than derived from $0:

REACT_NATIVE_CCACHE_CONFIGPATH=/path/to/react-native/scripts/xcode/ccache.conf
# Provide our config file if none is already provided
export CCACHE_CONFIGPATH="${CCACHE_CONFIGPATH:-$REACT_NATIVE_CCACHE_CONFIGPATH}"

exec "/opt/homebrew/bin/ccache" clang "$@"

Pods/ is regenerated by every pod install and is gitignored in the app templates, so the paths cannot go stale and nothing tracked gains a machine-specific value. Dropping the build setting also stops pod install writing an absolute ccache path into a tracked project.pbxproj.

There is deliberately no fallback when the ccache path is missing — silently continuing without ccache is the bug being fixed here, so the build fails with the path in the error and pod install puts it right.

I have only tested command-line xcodebuild, not a build started from Xcode.app.

Changelog:

[IOS] [FIXED] - Actually invoke ccache when it is enabled, and stop writing an absolute ccache path into the Xcode project

Test Plan:

rn-tester, clean Debug build for the iOS simulator, Xcode 26.6, Apple M4:

USE_CCACHE=1 bundle exec pod install
xcodebuild -workspace RNTesterPods.xcworkspace -scheme RNTester \
  -configuration Debug -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath /tmp/rnt build
wall ccache -s
before 215s 0 cacheable calls
after, empty cache 210s 1578/1582 cacheable
after, warm cache 19s 1578/1578 hits

Warm run is the same command after rm -rf /tmp/rnt/Build/Intermediates.noindex, so every path stays identical.

ruby utils-test.rb — three tests added for the generated script, covering both compilers and the embedded paths. The suite has 29 pre-existing errors on main, unchanged by this PR.

After pod install, project.pbxproj contains no CCACHE_BINARY; previously two occurrences carrying an absolute path.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 21, 2026
@facebook-github-tools facebook-github-tools Bot added the Contributor A React Native contributor. label Aug 21, 2026
@janicduplessis
janicduplessis force-pushed the ccache-resolve-binary-without-build-setting branch 3 times, most recently from c501680 to 2969cb2 Compare August 21, 2026 20:25
CCACHE_BINARY is set as an Xcode build setting by
set_ccache_compiler_and_linker_build_settings, and ccache-clang.sh reads it as an
environment variable. Xcode does not export build settings into the environment
of a compile task, so it is empty during a build and

    exec $CCACHE_BINARY clang "$@"

word-splits down to plain clang. ccache is never invoked, and every translation
unit pays for a shell fork that achieves nothing.

Verified by logging the variable from inside the launcher during a clean
rn-tester build: empty on all 1578 compiler invocations, with 0 cacheable calls.

The build setting came from react#48257, which fixed a real problem -- builds started
from Xcode.app have no Homebrew on PATH. The intent was right, but the delivery
mechanism is not available to a compiler launcher: Xcode passes it neither build
settings nor arguments (a CC value containing arguments fails to spawn).

pod install now generates the launchers into Pods/ with both paths resolved at
install time, and points CC/CXX at those. The generated scripts are the ones this
removes, with CCACHE_BINARY replaced by the resolved ccache path and the config
path absolute rather than derived from $0. Pods/ is regenerated by every pod
install and is gitignored in the app templates, so the paths cannot go stale and
nothing tracked gains a machine-specific value.

Dropping the build setting also stops pod install writing an absolute ccache path
into a tracked project.pbxproj.

rn-tester, clean Debug simulator build, Xcode 26.6, Apple M4:

  before        215s, 0 cacheable calls
  after, cold   210s, 1578/1582 cacheable
  after, warm    19s, 1578/1578 hits
@janicduplessis
janicduplessis force-pushed the ccache-resolve-binary-without-build-setting branch from 2969cb2 to 1674751 Compare August 21, 2026 20:32
@janicduplessis
janicduplessis marked this pull request as ready for review August 22, 2026 03:11
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Contributor A React Native contributor. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant