Skip to content

Conversation

@chrfalch
Copy link
Collaborator

Summary:

To solve our problem with header files from the React.XCFramework not being consumable due to the legacy Cocoapods headers, we used to point all header search / resolving into the Pods/Headers folder when building even with the framework installed.

This is a problem since an xcframework expects a modular header structure that can be consumed from within the headers folder of the framework.

The headers are used for both Objective-c compiling and for creating clang modules that can be consumed by Swift in our setup.

This commit fixes the above issues and makes a modular clang virtual file system from the header files we distribute. This vfs-overlay file will then be used by the rncore.rb script when installing the 'React-Core-prebuilt' pod and map the header files requested in the source code to the actual location on disk where the React.xcframework headers are installed.

Here are the changes:

  • Added vfs.js with types for creating clang virtual file system overlays
  • Added resolving the paths in the vfs file to the actual install path
  • Added installing the vfs overlay with the switch -ivfsoverlay <path> to compiler settings for both obj-c and swift on pod installation
  • Add vfs targets to the app target on post install

Changelog:

[IOS] [FIXED] - added support for clang virtual file system in React.XCFramework

Test Plan:

Run RNTester with prebuilt

To be able to change the target xcconfig from within `add_rn_core`, we need to make sure it is not overwritten by the line that sets the config.

This commit fixes this by moving it after the line:

`spec.pod_target_xcconfig = current_config`
A small cleanup to make the directory structure of the header file template when building xcframeworks.

Umbrella and module map templates are now moved into templates folder.
To make the later VFS overlays work, our React umbrella header needs to use angled import syntax instead of quoted".

This is so that the compiler will look up by module and not only by path.
Replace the regex-based approach for parsing podspec files with a declarative configuration system for header file collection:

Add headers-config.js with explicit podspec configurations defining header patterns, directories, and subspecs

- Add vfs.js to generate VFS overlay YAML files for Clang virtual file system support
- Refactor headers.js to use the new configuration-based approach with support for nested subspecs and path preservation
- Update xcframework.js to handle the new header mapping structure with source/target paths
- This provides more reliable and maintainable header file collection for XCFramework builds by avoiding fragile regex parsing of Ruby podspec files.
@chrfalch chrfalch requested a review from cipolleschi December 10, 2025 14:15
@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 Dec 10, 2025
@facebook-github-bot facebook-github-bot added p: Expo Partner: Expo Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Dec 10, 2025
@github-actions
Copy link

Job Summary for Gradle

Test All :: run_fantom_tests
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
react-native-github :private:react-native-fantom:buildFantomTester 9.0.0 Build Scan not published

@github-actions
Copy link

Job Summary for Gradle

Test All :: run_fantom_tests
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
react-native-github :private:react-native-fantom:buildFantomTester 9.0.0 Build Scan not published

Now it reads from podspec files, except for some special cases that we have in the config file.

Updated RCTSwiftUIWrapper.podspec to use podspec_sources (which we use to detect source)

I tested this against the header files I got with the previous iteration, and also with the ones installed by Cocoapods.
To solve our problem with header files from the React.XCFramework not being consumable due to the legacy Cocoapods headers, we used to point all header search / resolving into the Pods/Headers folder when building even with the framework installed.

This is a problem since an xcframework expects a modular header structure that can be consumed from within the headers folder of the framework.

The headers are used for both Objective-c compiling and for creating clang modules that can be consumed by Swift in our setup.

This commit fixes the above issues and makes a modular clang virtual file system from the header files we distribute. This vfs-overlay file will then be used by the `rncore.rb` script when installing the 'React-Core-prebuilt' pod and map the header files requested in the source code to the actual location on disk where the React.xcframework headers are installed.

Here are the changes:

- Added vfs.js with types for creating clang virtual file system overlays
- Added resolving the paths in the vfs file to the actual install path
- Added installing the vfs overlay with the switch `-ivfsoverlay <path>` to compiler settings for both obj-c and swift on pod installation
- Add vfs targets to the app target on post install
@chrfalch chrfalch force-pushed the chrfalch/react-precompile-add-vfs-support branch from 3e2aec1 to ed64fda Compare December 11, 2025 08:58
@github-actions
Copy link

Job Summary for Gradle

Test All :: run_fantom_tests
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
react-native-github :private:react-native-fantom:buildFantomTester 9.0.0 Build Scan not published

Had some podspecs with header_dir set to a variable that wasn't emitted correctly in the VFS file.

This commit fixes this by adding explicit reading of header-dir as well as exceptions for the specs that had variables.

- Tested comparing the output from a regular pod install with the generated header files.
- Tested with RNTester
- Tested in BareExpo with prebuild Expo modules and full compile.
Tried to build some smartness in last comitt - not working in a generic way so I reverted it.

This is handled by the exception in header-config.js instead.
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. p: Expo Partner: Expo Partner 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.

3 participants