diff --git a/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec b/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec new file mode 100644 index 00000000000..799bd101b08 --- /dev/null +++ b/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec @@ -0,0 +1,75 @@ +# 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" + +begin + react_native_path = File.dirname(Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native", + {paths: [process.argv[1]]}, + )', __dir__]).strip + ) +rescue => e + # Fallback to the parent directory if the above command fails (e.g when building locally in OOT Platform) + react_native_path = File.join(__dir__, "..", "..") +end + +# package.json +package = JSON.parse(File.read(File.join(react_native_path, "package.json"))) +version = package['version'] + +source = ReactNativeDependenciesUtils.podspec_source_download_prebuild_release_tarball() + +Pod::Spec.new do |spec| + spec.name = 'ReactNativeDependencies' + spec.version = version + spec.summary = 'React Native Dependencies' + spec.description = 'ReactNativeDependencies is a podspec that contains all the third-party dependencies of React Native.' + spec.homepage = 'https://github.com/facebook/react-native' + spec.license = package['license'] + spec.authors = 'meta' + spec.platforms = min_supported_versions + spec.user_target_xcconfig = { + 'WARNING_CFLAGS' => '-Wno-comma -Wno-shorten-64-to-32', + } + + spec.source = source + spec.preserve_paths = '**/*.*' + spec.vendored_frameworks = 'framework/packages/react-native/third-party/ReactNativeDependencies.xcframework' + spec.header_mappings_dir = 'Headers' + spec.source_files = 'Headers/**/*.{h,hpp}' + spec.prepare_command = <<-CMD + mkdir -p Headers + rsync -a react-native/third-party/ReactNativeDependencies.xcframework/ios-arm64/ReactNativeDependencies.framework/Headers/ Headers + mkdir -p framework/packages/react-native + rsync -a --remove-source-files react-native/ framework/packages/react-native/ + find react-native/ -type d -empty -delete + CMD + + script_phase = { + :name => "[RNDeps] Replace React Native Dependencies 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 + + "$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 diff --git a/packages/react-native/third-party-podspecs/replace_dependencies_version.js b/packages/react-native/third-party-podspecs/replace_dependencies_version.js new file mode 100644 index 00000000000..0138a7dc1eb --- /dev/null +++ b/packages/react-native/third-party-podspecs/replace_dependencies_version.js @@ -0,0 +1,107 @@ +/** + * 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. + * + * @format + */ + +'use strict'; + +const {execSync} = require('child_process'); +const fs = require('fs'); +const yargs = require('yargs'); + +const LAST_BUILD_FILENAME = 'ReactNativeDependencies/.last_build_configuration'; + +function validateBuildConfiguration(configuration) { + if (!['Debug', 'Release'].includes(configuration)) { + throw new Error(`Invalid configuration ${configuration}`); + } +} + +function validateVersion(version) { + if (version == null || version === '') { + throw new Error('Version cannot be empty'); + } +} + +function shouldReplaceRnDepsConfiguration(configuration) { + const fileExists = fs.existsSync(LAST_BUILD_FILENAME); + + if (fileExists) { + console.log(`Found ${LAST_BUILD_FILENAME} file`); + const oldConfiguration = fs.readFileSync(LAST_BUILD_FILENAME).toString(); + if (oldConfiguration === configuration) { + console.log( + 'Same config of the previous build. No need to replace RNDeps', + ); + return false; + } + } + + // Assumption: if there is no stored last build, we assume that it was build for debug. + if (!fileExists && configuration === 'Debug') { + console.log( + 'No previous build detected, but Debug Configuration. No need to replace RNDeps', + ); + return false; + } + + return true; +} + +function replaceRNDepsConfiguration(configuration, version, podsRoot) { + const tarballURLPath = `${podsRoot}/ReactNativeDependencies-artifacts/rndeps-ios-${version.toLowerCase()}-${configuration.toLowerCase()}.tar.gz`; + + const finalLocation = 'ReactNativeDependencies/framework'; + console.log('Preparing the final location', finalLocation); + fs.rmSync(finalLocation, {force: true, recursive: true}); + fs.mkdirSync(finalLocation, {recursive: true}); + + console.log('Extracting the tarball', tarballURLPath); + execSync(`tar -xf ${tarballURLPath} -C ${finalLocation}`); +} + +function updateLastBuildConfiguration(configuration) { + console.log(`Updating ${LAST_BUILD_FILENAME} with ${configuration}`); + fs.writeFileSync(LAST_BUILD_FILENAME, configuration); +} + +function main(configuration, version, podsRoot) { + validateBuildConfiguration(configuration); + validateVersion(version); + + if (!shouldReplaceRnDepsConfiguration(configuration)) { + return; + } + + replaceRNDepsConfiguration(configuration, version, podsRoot); + updateLastBuildConfiguration(configuration); + console.log('Done replacing React Native Dependencies'); +} + +// This script is executed in the Pods folder, which is usually not synched to Github, so it should be ok +const argv = yargs + .option('c', { + alias: 'configuration', + description: + 'Configuration to use to download the right React Native Dependencies version. Allowed values are "Debug" and "Release".', + }) + .option('r', { + alias: 'reactNativeVersion', + description: + 'The Version of React Native associated with the React Native Dependencies tarball.', + }) + .option('p', { + alias: 'podsRoot', + description: 'The path to the Pods root folder', + }) + .usage('Usage: $0 -c Debug -r -p ').argv; + +const configuration = argv.configuration; +const version = argv.reactNativeVersion; +const podsRoot = argv.podsRoot; + +main(configuration, version, podsRoot); diff --git a/packages/rn-tester/RNTesterPods.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/rn-tester/RNTesterPods.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000000..0c67376ebac --- /dev/null +++ b/packages/rn-tester/RNTesterPods.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + +