Skip to content

Commit 376bd0e

Browse files
chrfalchmeta-codesync[bot]
authored andcommitted
refactor(ios): remove clang VFS overlay, resolve headers via new ReactNativeHeaders framework (#57285)
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 `-ivfsoverlay` flags 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.xcframework`** — each slice's `React.framework` carries every `<React/...>` header plus a framework module map, so `#import <React/...>` and `import React` resolve through `FRAMEWORK_SEARCH_PATHS` automatically. - **`ReactNativeHeaders.xcframework`** (new, headers-only) — carries every other namespace (`<react/...>`, `<yoga/...>`, `folly`, `glog`, …), shipped alongside in the prebuilt tarball and exposed via a single header search path. - This makes `ReactNativeDependencies` binary-only. No clang VFS overlay, no per-target `-ivfsoverlay` flags. The layout is driven by a single source of truth (`headers-spec.js`, rules R1–R11) 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 change needed is bare-form angle includes (`#import <RCTAppDelegate.h>` → `#import <React/RCTAppDelegate.h>`). **Consumer surfaces the flattened layout initially dropped are restored** (validated against Expo and community Fabric modules): - Private headers (`RCTBridge+Private.h` + the Fabric `RCTComponentView*` family) are exposed in the `React` module map — modular where safe, `textual` where they reach C++ — so frameworks like Expo compile unchanged, incl. Swift access to `RCTBridge.moduleRegistry`. - `React_RCTAppDelegate-umbrella.h` is re-emitted (derived from the live header set) for consumers probing it via `__has_include`. - Sources shipping under multiple include spellings (`React/X.h` + legacy `CoreModules/…`, `RCTImage/…`, bare aliases — 116 today) keep content at ONE module-owned spelling; other spellings become generated redirect shims, so `-fmodules` consumers cannot hit duplicate declarations. - The `React-RCTFabric` facade re-vends `RCTFabricComponentsPlugins.h` at `header_dir "React"`, keeping community Fabric modules' quoted `#import "RCTFabricComponentsPlugins.h"` working as with source pods. **The layout is verified at generator time** (`headers-verify.js`, runs in the prebuild compose CI job): unresolvable includes ratchet against a committed baseline, composed module maps/umbrellas must byte-match the spec render, and consumer-shaped compile smokes must pass (the `React` module, every namespace module, an Expo-shaped ObjC++ fixture, and a Swift `moduleRegistry` fixture). Fail-closed guards cover header collisions, allowlist drift, and missing OR undeclared third-party deps namespaces (the latter surfaced `SocketRocket`, which is deliberately NOT relocated — the real pod vends it, and textual copies collide under `use_frameworks`; the gate asserts its absence). **Key changes** - **New**: `headers-spec.js` (the executable layout contract, R1–R11), `headers-compose.js` (emitter for both xcframeworks), `headers-inventory.js` (podspec-driven header classifier feeding the spec + a diagnostic manifest), `headers-verify.js` (generator-time gate + CI step), `__docs__/headers-rules.md` (rules + rationale). - **Removed**: `vfs.js`, VFS types in `types.js`, and the VFS processing/flag-injection paths in `rncore.rb` and `xcframework.js`. - **Updated**: `React-Core-prebuilt.podspec` (vends both xcframeworks, flattens `ReactNativeHeaders` headers into `Headers/` via `prepare_command`, fails closed on incomplete tarballs), `rncore.rb` / `react_native_pods.rb` (header search path instead of overlay flags), `prebuild-ios-core.yml` (core tarball ships both xcframeworks; compose job verifies the composed headers), README (VFS docs replaced with the new model). - Added facades to the Podspecs that shouldn't be in use when running using precompiled frameworks to satisfy dependencies as empty pod-specs (with the single `RCTFabricComponentsPlugins.h` re-vend exception noted above). ## Changelog: [IOS] [CHANGED] - Remove the Clang VFS overlay from prebuilt React Native Core; resolve headers via React.xcframework + a new headers-only ReactNativeHeaders.xcframework Pull Request resolved: #57285 Test Plan: - [x] rn-tester builds against the prebuilt `React-Core-prebuilt` pod (Debug + Release) with no `-ivfsoverlay` flags present in the generated xcconfigs. - [x] rn-tester builds against React native source code (without any prebuilt artifacts) - [x] `#import <React/...>`, `import React;`, and the relocated namespaces (`<react/...>`, `<yoga/...>`, `folly`/`glog`) all resolve. - [x] Prebuilt tarball contains both `React.xcframework` and `ReactNativeHeaders.xcframework`; pod install flattens headers into `React-Core-prebuilt/Headers`. - [x] Switch RN-tester between Debug/Release and verify that both `React.xcframework` and `ReactNativeHeaders.xcframework` are changed between debug and release correctly. - [x] `headers-verify.js` gate green on Debug and Release composes (`-Werror=non-modular-include-in-framework-module` never trips in consumer builds). - [x] `private/helloworld` builds against the prebuilt core (CocoaPods path). - [x] Expo SDK compiles against the prebuilt artifacts (private headers, `React_RCTAppDelegate` umbrella probe, Fabric quoted imports). Reviewed By: fabriziocucci Differential Revision: D111448598 Pulled By: cipolleschi fbshipit-source-id: 72bc2f37765ad425722161a038e410ba976858a5
1 parent 713ae6b commit 376bd0e

22 files changed

Lines changed: 3433 additions & 1074 deletions

.github/workflows/prebuild-ios-core.yml

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,22 @@ jobs:
157157
pattern: prebuild-ios-core-headers-${{ matrix.flavor }}-*
158158
path: packages/react-native/.build/headers
159159
merge-multiple: true
160+
- name: Download ReactNativeDependencies
161+
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
162+
uses: actions/download-artifact@v7
163+
with:
164+
name: ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz
165+
path: /tmp/third-party/
166+
- name: Extract ReactNativeDependencies
167+
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
168+
shell: bash
169+
run: |
170+
# ReactNativeHeaders.xcframework (built by the compose step) folds in
171+
# the third-party deps namespaces (folly/glog/boost/...), so the deps
172+
# headers must be staged here too — not just in build-slices.
173+
tar -xzf /tmp/third-party/ReactNativeDependencies${{ matrix.flavor }}.xcframework.tar.gz -C /tmp/third-party/
174+
mkdir -p packages/react-native/third-party/
175+
mv /tmp/third-party/packages/react-native/third-party/ReactNativeDependencies.xcframework packages/react-native/third-party/ReactNativeDependencies.xcframework
160176
- name: Setup Keychain
161177
if: ${{ steps.restore-ios-xcframework.outputs.cache-hit != 'true' && env.REACT_ORG_CODE_SIGNING_P12_CERT != '' }}
162178
uses: apple-actions/import-codesign-certs@v3 # https://github.com/marketplace/actions/import-code-signing-certificates
@@ -173,11 +189,24 @@ jobs:
173189
run: |
174190
cd packages/react-native
175191
node scripts/ios-prebuild -c -f "${{ matrix.flavor }}" -i "React Org"
192+
- name: Verify composed headers
193+
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
194+
run: |
195+
# Generator-time header gate: include-health ratchet, structural
196+
# byte-compare of module maps/umbrellas against the spec render, and
197+
# compile smokes (React module + every namespace module + the
198+
# privileged-consumer/Expo fixtures). Catches consumer-facing header
199+
# regressions here instead of in downstream builds.
200+
cd packages/react-native
201+
node scripts/ios-prebuild/headers-verify.js --flavor "${{ matrix.flavor }}"
176202
- name: Compress and Rename XCFramework
177203
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
178204
run: |
179205
cd packages/react-native/.build/output/xcframeworks/${{matrix.flavor}}
180-
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework
206+
# Ship BOTH xcframeworks: React-Core-prebuilt's prepare_command flattens
207+
# ReactNativeHeaders.xcframework's Headers (incl. module.modulemap) into the
208+
# pod. Omitting it leaves consumers without React-Core-prebuilt/Headers/module.modulemap.
209+
tar -cz -f ../ReactCore${{matrix.flavor}}.xcframework.tar.gz React.xcframework ReactNativeHeaders.xcframework
181210
- name: Compress and Rename dSYM
182211
if: steps.restore-ios-xcframework.outputs.cache-hit != 'true'
183212
run: |

packages/react-native/React-Core-prebuilt.podspec

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,60 @@ Pod::Spec.new do |s|
1717
s.author = "Meta Platforms, Inc. and its affiliates"
1818
s.platforms = min_supported_versions
1919
s.source = source
20+
21+
# We vend two xcframeworks that ship together in the prebuilt tarball:
22+
# - React.xcframework: the compiled core. Its per-slice React.framework carries
23+
# every <React/...> header + the framework module map, so `#import <React/...>`
24+
# and `@import React;` resolve through FRAMEWORK_SEARCH_PATHS automatically.
25+
# - ReactNativeHeaders.xcframework: headers-only. Carries every other namespace
26+
# (<react/...>, <yoga/...>, folly, glog, ...). Its headers are flattened into a
27+
# top-level Headers/ (see prepare_command) and exposed via the standard pod
28+
# header search path. (<hermes/...> is supplied by the hermes-engine pod here;
29+
# it is folded into ReactNativeHeaders only on the SwiftPM consumer side.)
30+
# There is no clang VFS overlay.
2031
s.vendored_frameworks = "React.xcframework"
2132

2233
s.preserve_paths = '**/*.*'
23-
s.header_mappings_dir = 'React.xcframework/Headers'
24-
s.source_files = 'React.xcframework/Headers/**/*.{h,hpp}'
25-
26-
s.module_name = 'React'
27-
s.module_map = 'React.xcframework/Modules/module.modulemap'
28-
s.public_header_files = 'React.xcframework/Headers/**/*.h'
34+
s.header_mappings_dir = 'Headers'
35+
s.source_files = 'Headers/**/*.{h,hpp}'
36+
s.public_header_files = 'Headers/**/*.h'
2937

3038
add_rn_third_party_dependencies(s)
3139

32-
# We need to make sure that the React.xcframework is copied correctly - in the downloaded tarball
33-
# the root directory is the framework, but when using it we need to have it in a subdirectory
34-
# called React.xcframework, so we need to move the contents of the tarball into that directory.
35-
# This is done in the prepare_command.
36-
# We need to make sure that the headers are copied to the right place - local tar.gz has a different structure
37-
# than the one from the maven repo
40+
# The downloaded tarball ships React.xcframework and ReactNativeHeaders.xcframework
41+
# at its root. We make sure React.xcframework is in its own subdirectory (the Maven
42+
# tarball lays the framework contents at the root; the local tar.gz has a different
43+
# structure) and flatten ReactNativeHeaders' headers into a top-level Headers/ dir
44+
# so CocoaPods exposes them on the header search path.
3845
s.prepare_command = <<~'CMD'
3946
CURRENT_PATH=$(pwd)
4047
XCFRAMEWORK_PATH="${CURRENT_PATH}/React.xcframework"
4148
42-
# Check if XCFRAMEWORK_PATH is empty
43-
if [ -z "$XCFRAMEWORK_PATH" ]; then
44-
echo "ERROR: XCFRAMEWORK_PATH is empty."
45-
exit 0
49+
# Flatten ReactNativeHeaders' headers (identical across slices) into Headers/
50+
# BEFORE we sweep stray root entries into React.xcframework. Fail closed:
51+
# a tarball without ReactNativeHeaders.xcframework (an artifact published
52+
# before the headers-spec layout, or a truncated download) would otherwise
53+
# yield a green install with an empty Headers/ and every <react/...> or
54+
# <yoga/...> include failing much later, far from the cause.
55+
mkdir -p Headers
56+
RNH_XCFRAMEWORK_PATH=$(find "$CURRENT_PATH" -type d -name "ReactNativeHeaders.xcframework" | head -n 1)
57+
if [ -z "$RNH_XCFRAMEWORK_PATH" ]; then
58+
echo "[React-Core-prebuilt] ERROR: ReactNativeHeaders.xcframework not found in the prebuilt tarball." >&2
59+
echo "The artifact predates the headers-spec layout or is incomplete; use a matching react-native version." >&2
60+
exit 1
61+
fi
62+
RNH_HEADERS_PATH=$(find "$RNH_XCFRAMEWORK_PATH" -type d -name "Headers" | head -n 1)
63+
if [ -z "$RNH_HEADERS_PATH" ]; then
64+
echo "[React-Core-prebuilt] ERROR: no Headers directory inside $RNH_XCFRAMEWORK_PATH." >&2
65+
exit 1
4666
fi
67+
cp -R "$RNH_HEADERS_PATH/." Headers
68+
rm -rf "$RNH_XCFRAMEWORK_PATH"
4769
4870
mkdir -p "${XCFRAMEWORK_PATH}"
49-
find "$CURRENT_PATH" -mindepth 1 -maxdepth 1 ! -name "$(basename "$XCFRAMEWORK_PATH")" -exec mv {} "$XCFRAMEWORK_PATH" \;
71+
find "$CURRENT_PATH" -mindepth 1 -maxdepth 1 \
72+
! -name "$(basename "$XCFRAMEWORK_PATH")" ! -name "Headers" \
73+
-exec mv {} "$XCFRAMEWORK_PATH" \;
5074
CMD
5175

5276
# If we are passing a local tarball, we don't want to switch between Debug and Release

packages/react-native/scripts/cocoapods/fabric.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def setup_fabric!(react_native_path: "../node_modules/react-native")
1111
pod 'React-Fabric', :path => "#{react_native_path}/ReactCommon"
1212
pod 'React-FabricComponents', :path => "#{react_native_path}/ReactCommon"
1313
pod 'React-graphics', :path => "#{react_native_path}/ReactCommon/react/renderer/graphics"
14-
pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true
14+
rncore_pod 'React-RCTFabric', :path => "#{react_native_path}/React", :modular_headers => true
1515
pod 'React-ImageManager', :path => "#{react_native_path}/ReactCommon/react/renderer/imagemanager/platform/ios"
1616
pod 'React-FabricImage', :path => "#{react_native_path}/ReactCommon"
1717
end

packages/react-native/scripts/cocoapods/rncore.rb

Lines changed: 33 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,16 @@
1111

1212
### Adds ReactNativeCore-prebuilt as a dependency to the given podspec if we're not
1313
### building ReactNativeCore from source (then this function does nothing).
14+
###
15+
### `<React/...>` resolves through the vendored React.framework; every other namespace
16+
### (`<react/...>`, `<yoga/...>`, `<hermes/...>`, ...) resolves through the flattened
17+
### ReactNativeHeaders headers that React-Core-prebuilt exposes. The header search path
18+
### and the ReactNativeHeaders module-map activation are NOT added here: they are applied
19+
### post-install by configure_aggregate_xcconfig, which covers aggregate, third-party AND
20+
### these pods from a single injection site. No clang VFS overlay.
1421
def add_rncore_dependency(s)
1522
if !ReactNativeCoreUtils.build_rncore_from_source()
16-
# Add the dependency
1723
s.dependency "React-Core-prebuilt"
18-
19-
current_pod_target_xcconfig = s.to_hash["pod_target_xcconfig"] || {}
20-
current_pod_target_xcconfig = current_pod_target_xcconfig.to_h unless current_pod_target_xcconfig.is_a?(Hash)
21-
22-
# Add VFS overlay flags for both Objective-C and Swift
23-
# The VFS overlay file is pre-resolved at pod install time for each platform slice.
24-
# We reference it directly in the xcframework using the React-VFS.yaml file that
25-
# is written to the React-Core-prebuilt folder during setup_vfs_overlay.
26-
# See scripts/ios-prebuild/__docs__/README.md for more details on VFS overlays.
27-
vfs_overlay_flag = "-ivfsoverlay $(PODS_ROOT)/React-Core-prebuilt/React-VFS.yaml"
28-
current_pod_target_xcconfig["OTHER_CFLAGS"] ||= "$(inherited)"
29-
current_pod_target_xcconfig["OTHER_CFLAGS"] += " #{vfs_overlay_flag}"
30-
current_pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"] ||= "$(inherited)"
31-
current_pod_target_xcconfig["OTHER_CPLUSPLUSFLAGS"] += " #{vfs_overlay_flag}"
32-
# For Swift, we need to use -Xcc to pass flags to the underlying Clang compiler
33-
# Both the flag and its argument need separate -Xcc prefixes
34-
current_pod_target_xcconfig["OTHER_SWIFT_FLAGS"] ||= "$(inherited)"
35-
current_pod_target_xcconfig["OTHER_SWIFT_FLAGS"] += " -Xcc -ivfsoverlay -Xcc $(PODS_ROOT)/React-Core-prebuilt/React-VFS.yaml"
36-
37-
s.pod_target_xcconfig = current_pod_target_xcconfig
3824
end
3925
end
4026

@@ -521,96 +507,65 @@ def self.get_nightly_npm_version()
521507
return latest_nightly
522508
end
523509

524-
# Processes the VFS overlay file from the React.xcframework to resolve the ${ROOT_PATH} placeholder.
525-
# This method should be called from react_native_post_install after pod install completes.
510+
# Single post-install injection site for the prebuilt header resolution. Adds the
511+
# ReactNativeHeaders search path + module-map activation to the aggregate (main app)
512+
# target AND every pod target — RN core pods, third-party pods alike. (add_rncore_dependency
513+
# only declares the React-Core-prebuilt dependency; it no longer touches xcconfigs.)
526514
#
527-
# The VFS overlay file maps header import paths to their actual locations within the xcframework.
528-
# Since the xcframework contains platform-specific slices, we generate a resolved VFS file for each
529-
# slice and also create a default VFS file that can be used immediately (before script phases run).
530-
def self.process_vfs_overlay()
531-
return if @@build_from_source
532-
533-
prebuilt_path = File.join(Pod::Config.instance.project_pods_root, "React-Core-prebuilt")
534-
xcframework_path = File.join(prebuilt_path, "React.xcframework")
535-
vfs_template_path = File.join(xcframework_path, "React-VFS-template.yaml")
536-
537-
unless File.exist?(vfs_template_path)
538-
rncore_log("VFS overlay template not found at #{vfs_template_path}", :error)
539-
exit 1
540-
end
541-
542-
rncore_log("Processing VFS overlay file...")
543-
544-
# Read the template content
545-
vfs_template_content = File.read(vfs_template_path)
546-
547-
# Write the VFS file - use the top-level xcframework path
548-
# so that ${ROOT_PATH}/Headers points to the xcframework's Headers folder
549-
resolved_vfs_content = vfs_template_content.gsub('${ROOT_PATH}', xcframework_path)
550-
resolved_vfs_path = File.join(prebuilt_path, "React-VFS.yaml")
551-
File.write(resolved_vfs_path, resolved_vfs_content)
552-
rncore_log(" Created VFS overlay at #{resolved_vfs_path}")
553-
554-
rncore_log("VFS overlay setup complete")
555-
end
556-
557-
# Configures the xcconfig files for aggregate (main app) targets to enable VFS overlay for React Native Core.
558-
# This is needed because the main app target does not go through podspec processing,
559-
# so it won't get the VFS overlay flags from add_rncore_dependency.
515+
# `<React/...>` resolves through the vendored React.framework; this adds the search
516+
# path to the flattened ReactNativeHeaders headers (every other namespace). There is
517+
# no clang VFS overlay.
560518
#
561519
# Parameters:
562520
# - installer: The CocoaPods installer object
563521
def self.configure_aggregate_xcconfig(installer)
564522
return if @@build_from_source
565523

566-
prebuilt_path = File.join(Pod::Config.instance.project_pods_root, "React-Core-prebuilt")
567-
vfs_overlay_path = File.join(prebuilt_path, "React-VFS.yaml")
568-
569-
unless File.exist?(vfs_overlay_path)
570-
rncore_log("VFS overlay not found at #{vfs_overlay_path}, skipping prebuilt xcconfig configuration", :error)
571-
exit 1
572-
end
573-
574524
rncore_log("Configuring xcconfig for prebuilt React Native Core...")
575525

576-
vfs_overlay_flag = " -ivfsoverlay \"#{vfs_overlay_path}\""
577-
swift_vfs_overlay_flag = " -Xcc -ivfsoverlay -Xcc \"#{vfs_overlay_path}\""
526+
headers_search_path = " \"$(PODS_ROOT)/React-Core-prebuilt/Headers\""
578527

579-
# Add flags to aggregate target xcconfigs (these are used by the main app target)
528+
# Add the header search path to aggregate target xcconfigs (used by the main app target)
580529
installer.aggregate_targets.each do |aggregate_target|
581530
aggregate_target.xcconfigs.each do |config_name, config_file|
582-
add_vfs_overlay_flags(config_file.attributes, vfs_overlay_flag, swift_vfs_overlay_flag)
531+
add_prebuilt_header_search_paths(config_file.attributes, headers_search_path)
583532
xcconfig_path = aggregate_target.xcconfig_path(config_name)
584533
config_file.save_as(xcconfig_path)
585534
end
586535
end
587536

588-
# Add flags to ALL pod targets (for third-party pods that don't call add_rncore_dependency)
537+
# Add the header search path to ALL pod targets (for third-party pods that don't call add_rncore_dependency)
589538
installer.pod_targets.each do |pod_target|
590539
pod_target.build_settings.each do |config_name, build_settings|
591540
xcconfig_path = pod_target.xcconfig_path(config_name)
592541
next unless File.exist?(xcconfig_path)
593542

594543
xcconfig = Xcodeproj::Config.new(xcconfig_path)
595544

596-
# Check if VFS overlay is already present
597-
other_cflags = xcconfig.attributes["OTHER_CFLAGS"] || ""
598-
next if other_cflags.include?("ivfsoverlay")
545+
# Skip if the prebuilt header search path is already present
546+
header_search_paths = xcconfig.attributes["HEADER_SEARCH_PATHS"] || ""
547+
next if header_search_paths.include?("React-Core-prebuilt/Headers")
599548

600-
add_vfs_overlay_flags(xcconfig.attributes, vfs_overlay_flag, swift_vfs_overlay_flag)
549+
add_prebuilt_header_search_paths(xcconfig.attributes, headers_search_path)
601550
xcconfig.save_as(xcconfig_path)
602551
end
603552
end
604553

605554
rncore_log("Prebuilt xcconfig configuration complete")
606555
end
607556

608-
# Helper method to add VFS overlay flags to an xcconfig attributes map
609-
def self.add_vfs_overlay_flags(attributes, vfs_overlay_flag, swift_vfs_overlay_flag)
610-
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_CFLAGS", vfs_overlay_flag)
611-
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_CPLUSPLUSFLAGS", vfs_overlay_flag)
612-
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_SWIFT_FLAGS", swift_vfs_overlay_flag)
557+
# Helper method to add the prebuilt ReactNativeHeaders header search path to an xcconfig attributes map
558+
def self.add_prebuilt_header_search_paths(attributes, headers_search_path)
559+
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "HEADER_SEARCH_PATHS", headers_search_path)
613560
# Suppress incomplete umbrella warnings for the prebuilt frameworks (it is expected, as our umbrella headers do not include all headers)
614561
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_SWIFT_FLAGS", " -Xcc -Wno-incomplete-umbrella")
562+
# Activate the ReactNativeHeaders module map so the relocated namespaces
563+
# (`yoga`, `RCTDeprecation`, `ReactNativeHeaders_react`, ...) are modular —
564+
# otherwise the React framework's clang explicit-module precompile trips
565+
# -Wnon-modular-include-in-framework-module on `<yoga/...>` / `<react/...>`.
566+
# Quoted so a $(PODS_ROOT) containing spaces stays a single clang argument.
567+
module_map_flag = " \"-fmodule-map-file=$(PODS_ROOT)/React-Core-prebuilt/Headers/module.modulemap\""
568+
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_CFLAGS", module_map_flag)
569+
ReactNativePodsUtils.add_flag_to_map_with_inheritance(attributes, "OTHER_SWIFT_FLAGS", " -Xcc" + module_map_flag)
615570
end
616571
end

0 commit comments

Comments
 (0)