packages/react-native/scripts/ios-prebuild/__docs__/README.md
This directory contains scripts for prebuilding React Native itself into XCFrameworks for iOS and related platforms.
These scripts automate the process of building React Native as a Swift Package and packaging it into XCFrameworks that can be distributed and consumed by iOS applications. The build process creates optimized frameworks for multiple architectures and platforms.
The prebuild scripts are used to:
Run the prebuild script from the command line:
cd packages/react-native
node scripts/ios-prebuild
If no options are passed, the script executes all the steps in this order:
| Option | Alias | Type | Default | Description |
|---|---|---|---|---|
--setup | -s | boolean | - | Download and setup dependencies |
--build | -b | boolean | - | Build dependencies/platforms |
--compose | -c | boolean | - | Compose XCFramework from built dependencies |
--platforms | -p | array | ['ios', 'ios-simulator', 'mac-catalyst'] | Specify one or more platforms to build for |
--flavor | -f | string | Debug | Specify the flavor to build: Debug or Release |
--identity | -i | string | - | Specify the code signing identity to use for signing the frameworks |
--help | - | boolean | - | Show help information |
The build produces:
The build system consists of several components:
cli.jsThe main entry point that orchestrates the build process. It:
build.jsHandles the Swift Package build process. It:
xcodebuild commands with appropriate flagsBUILD_LIBRARY_FOR_DISTRIBUTION=YES for binary
compatibilitytypes.jsDefines TypeScript/Flow type definitions for:
BuildFlavor: Debug or Release configurationsDestination: Target platforms (iOS, iOS Simulator, Catalyst, Vision,
visionOS)ArchiveOptions: Configuration options for the build processutils.jsProvides utility functions including:
The build process uses specific xcodebuild flags:
BUILD_LIBRARY_FOR_DISTRIBUTION=YES: Enables module stabilitySKIP_INSTALL=NO: Ensures frameworks are properly installedDEBUG_INFORMATION_FORMAT="dwarf-with-dsym": Generates debug symbolsOTHER_SWIFT_FLAGS="-no-verify-emitted-module-interface": Skips interface
verification (useful for React Native modules due to the header structure not
beeing modular)The generated XCFrameworks currently use CocoaPods-style header structures rather than standard framework header conventions. This may cause modularity issues when:
The prebuilt XCFrameworks use Clang's Virtual File System (VFS) overlay mechanism to enable header imports without modifying the actual header file structure. This is necessary because React Native's headers are organized differently than standard framework conventions.
The VFS overlay creates a virtual mapping between the import paths used in code
(e.g., #import <react/renderer/graphics/Size.h>) and the actual physical
locations of headers within the XCFramework. This allows the prebuilt frameworks
to work seamlessly while maintaining the original import syntax.
vfs.js)The vfs.js script creates a VFS overlay template during the prebuild process:
Header Collection (headers.js): Scans all podspec files in the React
Native package to discover header files and their target import paths.
VFS Structure Building: The buildVFSStructure() function creates a
hierarchical directory tree representation from the header mappings. Clang's
VFS overlay requires directories to contain their children in a tree
structure.
YAML Generation: The generateVFSOverlayYAML() function converts the VFS
structure into Clang's expected YAML format.
Template Creation: The generated overlay uses ${ROOT_PATH} as a
placeholder for the actual installation path. This template is included in
the XCFramework as React-VFS-template.yaml.
createVFSOverlay(rootFolder): Main entry point that generates the complete
VFS overlay YAML stringcreateVFSOverlayContents(rootFolder): Creates the VFS overlay object
structurebuildVFSStructure(mappings): Builds the hierarchical directory tree from
flat mappingsresolveVFSOverlay(vfsTemplate, rootPath): Replaces ${ROOT_PATH} with the
actual pathWhen consuming prebuilt frameworks via CocoaPods, the VFS overlay is processed
at pod install time by rncore.rb:
process_vfs_overlay()Called during react_native_post_install, this method:
React-VFS-template.yaml from the XCFramework${ROOT_PATH} placeholder with the actual XCFramework path$(PODS_ROOT)/React-Core-prebuilt/React-VFS.yamladd_rncore_dependency(s)Adds VFS overlay compiler flags to podspecs that depend on React Native:
# For C/C++ compilation
OTHER_CFLAGS += "-ivfsoverlay $(PODS_ROOT)/React-Core-prebuilt/React-VFS.yaml"
OTHER_CPLUSPLUSFLAGS += "-ivfsoverlay $(PODS_ROOT)/React-Core-prebuilt/React-VFS.yaml"
# For Swift compilation (flags passed to underlying Clang)
OTHER_SWIFT_FLAGS += "-Xcc -ivfsoverlay -Xcc $(PODS_ROOT)/React-Core-prebuilt/React-VFS.yaml"
configure_aggregate_xcconfig(installer)Configures VFS overlay flags for:
add_rncore_dependencyThis ensures all compilation units in the project can resolve React Native headers through the VFS overlay.
The VFS overlay uses Clang's hierarchical YAML format:
version: 0
case-sensitive: false
roots:
- name: '${ROOT_PATH}/Headers'
type: 'directory'
contents:
- name: 'react'
type: 'directory'
contents:
- name: 'renderer'
type: 'directory'
contents:
- name: 'Size.h'
type: 'file'
external-contents: '${ROOT_PATH}/Headers/React/react/renderer/Size.h'
The structure maps virtual paths (what the compiler sees) to physical paths (where the files actually exist in the XCFramework).
For consuming, debugging or troubleshooting when using Cocoapods scripts, you can use the following environment variables:
RCT_USE_PREBUILT_RNCORE: If set to 1, it will use the release tarball from
Maven instead of building from source.RCT_TESTONLY_RNCORE_TARBALL_PATH: TEST ONLY If set, it will use a local
tarball of RNCore if it exists.RCT_TESTONLY_RNCORE_VERSION: TEST ONLY If set, it will override the
version of RNCore to be used.RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS: If set to 1, it will download the dSYMs
for the prebuilt RNCore frameworks and install these in the framework folders