From 1a86ee17fb80cfa1b8bcff30f4f3d5cdb193900d Mon Sep 17 00:00:00 2001 From: Christian Falch Date: Mon, 23 Jun 2025 08:13:56 -0700 Subject: [PATCH] Add React-Core-prebuild.podspec to integrate React native core prebuilds using cocoapods (#52133) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/52133 Add React-Core-prebuild.podspec to integrate React native core prebuilds using cocoapods ## Context This PR introduces the first working version of building React Native apps on iOS using prebuilt RNCore and cocoapods. - Added React-Core-prebuilt.podspec for installing/consuming XCFrameworks - Added logic in react_native_pods.rb for switching between build from source and using prebuilts - Added rncore.rb - utilities for the ReactCore prebuilts - Updated rndependencies with some extra error handling modelled after rncode.rb - Added support for hard linking headers and modules in each inner framework in the XCFramework in xcframework.js ## Swift: To enable support for the objective-c types from swift, the swift compiler uses a module map to gather exports from the framework (module.modulemap). This file basically points to an umbrella header file that exports the valid objective-c types (non c++) to Swift. In addition these files are read from the DerivedData and not the project source - so it is a bit hard to control everyting. I was initially not able to use cocoapods own module definitions (module_name, module_file props) to use a custom module map. I finally found that these files are expected in the deriveddata (build folder) where only the active inner framework is copied - so then I had to hard link both module map and header files for each arch. ## Changelog: [IOS] [ADDED] - Add `React-Core-prebuild.podspec` to integrate React native core prebuilds using cocoapods Pull Request resolved: https://github.com/facebook/react-native/pull/52109 Test Plan: Run with RN Tester. We need to remove all extra pods from RNTester pod file since none of them are yet compatible with prebuilt (they reference non-prebuilt pods) Rollback Plan: Reviewed By: cortinico Differential Revision: D76980281 Pulled By: cipolleschi fbshipit-source-id: ce102837d6df6ab0fa2e55862cc0c954125bd362 --- .../react-native/React-Core-prebuilt.podspec | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 packages/react-native/React-Core-prebuilt.podspec diff --git a/packages/react-native/React-Core-prebuilt.podspec b/packages/react-native/React-Core-prebuilt.podspec new file mode 100644 index 00000000000..0e5281b7aa7 --- /dev/null +++ b/packages/react-native/React-Core-prebuilt.podspec @@ -0,0 +1,109 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +version = package['version'] + +source = ReactNativeCoreUtils.resolve_podspec_source() + +header_search_paths = [ + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt", + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt/RCTDeprecation", + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt/ReactCommon/yoga", + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt/ReactCommon", + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt/Libraries/AppDelegate", + "${PODS_ROOT}/Headers/Private/React-Core-prebuilt/Libraries", + + "$(REACT_NATIVE_PATH)/React/Base", + "$(REACT_NATIVE_PATH)/ReactCommon", + "$(REACT_NATIVE_PATH)/Libraries", + "$(REACT_NATIVE_PATH)/ReactApple", + "$(REACT_NATIVE_PATH)/ReactCxxPlatform", + "$(REACT_NATIVE_PATH)/ReactCommon/react/runtime/platform/ios", + "${REACT_NATIVE_PATH}/ReactCommon/jsi", + "$(REACT_NATIVE_PATH)/ReactCommon/jsiexecutor/", + "$(REACT_NATIVE_PATH)/ReactCommon/react/nativemodule/samples/platform/ios", + "$(REACT_NATIVE_PATH)/ReactCommon/react/nativemodule/samples", +] + +Pod::Spec.new do |spec| + spec.name = 'React-Core-prebuilt' + spec.version = version + spec.summary = "Prebuilt core of React Native." + spec.homepage = "https://reactnative.dev/" + spec.description = 'Prebuilt React Native Core libraries and headers' + spec.homepage = 'https://github.com/facebook/react-native' + spec.license = package['license'] + spec.authors = 'meta' + spec.platforms = min_supported_versions + spec.source = source + + spec.vendored_frameworks = "React.xcframework" + + spec.preserve_paths = '**/*.*' + spec.header_mappings_dir = 'React.xcframework/Headers' + spec.source_files = 'React.xcframework/Headers/**/*.{h,hpp}' + + spec.module_name = 'React' + spec.module_map = 'React.xcframework/Modules/module.modulemap' + spec.public_header_files = 'React.xcframework/Headers/**/*.h' + + # Setup the consuming project's search paths + spec.user_target_xcconfig = { + "HEADER_SEARCH_PATHS" => header_search_paths, + "SWIFT_INCLUDE_PATHS" => "${PODS_ROOT}/Headers/Private/React-Core-prebuilt", + 'DEFINES_MODULE' => 'YES', + 'CLANG_ENABLE_MODULES' => 'YES', + } + + spec.pod_target_xcconfig = { + 'WARNING_CFLAGS' => '-Wno-comma -Wno-shorten-64-to-32', + "CLANG_CXX_LANGUAGE_STANDARD" => rct_cxx_language_standard(), + 'DEFINES_MODULE' => 'YES', + 'CLANG_ENABLE_MODULES' => 'YES', + } + + # We need to make sure that the React.xcframework is copied correctly - in the downloaded tarball + # the root directory is the framework, but when using it we need to have it in a subdirectory + # called React.xcframework, so we need to move the contents of the tarball into that directory. + # This is done in the prepare_command. + spec.prepare_command = <<~'CMD' + CURRENT_PATH=$(pwd) + XCFRAMEWORK_PATH="${CURRENT_PATH}/React.xcframework" + mkdir -p "${XCFRAMEWORK_PATH}" + find "$CURRENT_PATH" -mindepth 1 -maxdepth 1 ! -name "$(basename "$XCFRAMEWORK_PATH")" -exec mv {} "$XCFRAMEWORK_PATH" \; + CMD + + # If we are passing a local tarball, we don't want to switch between Debug and Release + if !ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"] + script_phase = { + :name => "[RNDeps] Replace React Native Core for the right configuration, if needed", + :execution_position => :before_compile, + :script => <<-EOS + . "$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh" + + CONFIG="Release" + if echo $GCC_PREPROCESSOR_DEFINITIONS | grep -q "DEBUG=1"; then + CONFIG="Debug" + fi + + # TODO(T228219721): Add this for React Native Core as well + ##### "$NODE_BINARY" "$REACT_NATIVE_PATH/third-party-podspecs/replace_dependencies_version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT" + EOS + } + + + # :always_out_of_date is only available in CocoaPods 1.13.0 and later + if Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.13.0') + # always run the script without warning + script_phase[:always_out_of_date] = "1" + end + + spec.script_phase = script_phase + end + +end