refactor(ios): remove clang VFS overlay, resolve headers via new ReactNativeHeaders framework#57285
Open
chrfalch wants to merge 2 commits into
Open
refactor(ios): remove clang VFS overlay, resolve headers via new ReactNativeHeaders framework#57285chrfalch wants to merge 2 commits into
chrfalch wants to merge 2 commits into
Conversation
The minimal machinery to build the packaged header structures: - headers-spec.js: the executable layout contract (rules R1-R8) — which namespaces are hoisted into the React framework, which carry module maps, and how collisions are rejected. - headers-inventory.js: scans the source tree and classifies every shipped header (language surface + modularizability bucket) — the input to the spec. computeInventory() feeds the build in-memory; the CLI writes a JSON manifest. - headers-compose.js: emits the layout — writes the <React/...> headers + umbrella + module map into each React.framework slice (detected by the framework's presence), and assembles the headers-only ReactNativeHeaders.xcframework (every other namespace + deps + Hermes). Called by xcframework.js during compose. This is the alternative header source that lets consumers resolve React Native headers without a clang VFS overlay. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Emit the headers-spec layout unconditionally and delete the VFS overlay across
JS, CI publish, and Ruby. Consumers resolve headers the way the SwiftPM branch
does: <React/...> from the vendored React.framework, every other namespace from
ReactNativeHeaders. No root Headers/ on the xcframework, no VFS.
JS:
- xcframework.js: always emit the React.framework spec layout and build
ReactNativeHeaders.xcframework (was gated behind RN_ZERO_I_LAYOUT=1). Remove
the legacy header path entirely — the podspec->root-Headers enumeration,
createModuleMapFile, and copyHeaderFilesToSlices — so the published
React.xcframework is a standard framework (Info.plist + per-slice
React.framework/{Headers,Modules}), no root Headers/ or Modules/. Ship
ReactNativeHeaders.xcframework inside the reactnative-core tarball (sibling of
React.xcframework) so the prebuilt pod can vend both; keep the standalone
ReactNativeHeaders.xcframework.tar.gz for the SPM path. Drop the
React-VFS-template.yaml emit and the ./vfs import.
- vfs.js: deleted (its only consumer was xcframework.js).
- types.js: drop the now-unused VFSEntry/VFSOverlay/HeaderMapping types.
- replace-rncore-version.js: drop the React-VFS.yaml preservation rationale.
Ruby/CocoaPods:
- React-Core-prebuilt.podspec: vend React.xcframework (its per-slice
React.framework + module map serves <React/...> and @import React via
FRAMEWORK_SEARCH_PATHS); flatten ReactNativeHeaders' headers into a top-level
Headers/ in prepare_command and expose them via the pod header search path.
Drop the VFS-era root header_mappings_dir/module_map.
- rncore.rb: remove the -ivfsoverlay injection and process_vfs_overlay;
add_rncore_dependency and configure_aggregate_xcconfig now add a
HEADER_SEARCH_PATHS to React-Core-prebuilt/Headers for podspec, aggregate, and
third-party targets.
- react_native_pods.rb: drop the process_vfs_overlay post-install call.
Docs: replace the "VFS Overlay System" section with the headers-spec layout;
drop the obsolete "Known Issues" (pre-headers-spec) section.
Verified end-to-end: prebuild compose produces a VFS-free, root-Headers-free
React.xcframework; rn-tester pod install + xcodebuild (prebuilt path) BUILD
SUCCEEDED with zero -ivfsoverlay.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| // namespace). The headers-only xcframework is a sibling of React.xcframework. | ||
| execSync( | ||
| `tar -czf ${tarFilePath} -C ${path.dirname(outputPath)} React.xcframework`, | ||
| `tar -czf ${tarFilePath} -C ${path.dirname(outputPath)} React.xcframework ${path.basename(headersXcfw)}`, |
| frameworkLog('Creating tar file: ' + headersTarPath); | ||
| try { | ||
| execSync( | ||
| `tar -czf ${headersTarPath} -C ${path.dirname(headersXcfw)} ReactNativeHeaders.xcframework`, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The prebuilt React.xcframework previously relied on a Clang VFS overlay (React-VFS.yaml) to make headers importable, because the headers were laid out in CocoaPods-style namespaced folders rather than standard framework conventions. The overlay had to be generated at build time, re-resolved at pod-install time per slice, and injected as
-ivfsoverlayflags into every Obj-C, C++, and Swift compile (including aggregate and third-party pod targets).This is fragile, hard to reason about, and incompatible with SwiftPM consumption.
This PR removes the VFS overlay entirely and resolves headers through standard framework/header-search-path mechanics instead.
Headers are now emitted into the artifact according to an explicit, executable spec:
<React/...>header plus a framework module map, so#import <React/...>and@import Reactresolve throughFRAMEWORK_SEARCH_PATHSautomatically.<react/...>,<yoga/...>,folly,glog, …), shipped alongside in the prebuilt tarball and exposed via a single header search path.ReactNativeDependenciesbinary-only.No clang VFS overlay, no per-target
-ivfsoverlayflags. The layout is driven by a single source of truth (headers-spec.js, rules R1–R8) that both the prebuild compose step and downstream SwiftPM tooling derive from, so the shipped header set cannot drift from the spec.Source headers are byte-identical to the repo — the only consumer-facing changes needed is bare-form angle includes (
#import <RCTAppDelegate.h>→#import <React/RCTAppDelegate.h>).Key changes
headers-spec.js(the executable layout contract),headers-compose.js(emitter for both xcframeworks),headers-inventory.js(podspec-driven header classifier feeding the spec + a diagnostic manifest).vfs.js, VFS types intypes.js, and the VFS processing/flag-injection paths inrncore.rbandxcframework.js.React-Core-prebuilt.podspec(vends both xcframeworks, flattens ReactNativeHeaders headers into Headers/ via prepare_command),rncore.rb/react_native_pods.rb(header search path instead of overlay flags), README (VFS docs replaced with the new model).Changelog
[IOS] [CHANGED] - Remove the Clang VFS overlay from prebuilt React Native Core; resolve headers via React.xcframework + a new headers-only ReactNativeHeaders.xcframework
Test Plan
React.xcframeworkandReactNativeHeaders.xcframeworkpod install flattens headers into React-Core-prebuilt/Headers.React.xcframeworkandReactNativeHeaders.xcframeworkare changed between debug and release correctly.