diff --git a/packages/react-native/React-Core-prebuilt.podspec b/packages/react-native/React-Core-prebuilt.podspec index 81ffdbd933d9..23aa9df84d2d 100644 --- a/packages/react-native/React-Core-prebuilt.podspec +++ b/packages/react-native/React-Core-prebuilt.podspec @@ -84,11 +84,7 @@ Pod::Spec.new do |s| :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 + . "$REACT_NATIVE_PATH/scripts/xcode/resolve-prebuilt-configuration.sh" "$NODE_BINARY" "$REACT_NATIVE_PATH/scripts/replace-rncore-version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT" EOS diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 973f18a8b239..00520250ee25 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -119,6 +119,7 @@ "scripts/xcode/ccache-clang.sh", "scripts/xcode/ccache-clang++.sh", "scripts/xcode/ccache.conf", + "scripts/xcode/resolve-prebuilt-configuration.sh", "scripts/xcode/with-environment.sh", "sdks/.hermesv1version", "sdks/hermes-engine", diff --git a/packages/react-native/scripts/__tests__/resolve-prebuilt-configuration-test.js b/packages/react-native/scripts/__tests__/resolve-prebuilt-configuration-test.js new file mode 100644 index 000000000000..6dffe7131864 --- /dev/null +++ b/packages/react-native/scripts/__tests__/resolve-prebuilt-configuration-test.js @@ -0,0 +1,83 @@ +/** + * 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 + * @noflow + */ + +'use strict'; + +const {execFileSync} = require('node:child_process'); +const path = require('node:path'); + +const SCRIPT = path.join( + __dirname, + '..', + 'xcode', + 'resolve-prebuilt-configuration.sh', +); + +function resolve(env) { + return execFileSync('/bin/sh', [SCRIPT], { + env: {...process.env, ...env}, + encoding: 'utf8', + }).trim(); +} + +describe('resolve-prebuilt-configuration', () => { + test('defaults to Release when no debug signals are present', () => { + expect( + resolve({ + CONFIGURATION: 'Release', + POD_CONFIGURATION_DEBUG: '', + GCC_PREPROCESSOR_DEFINITIONS: 'COCOAPODS=1', + }), + ).toBe('Release'); + }); + + test('selects Debug when CONFIGURATION is Debug', () => { + expect( + resolve({ + CONFIGURATION: 'Debug', + POD_CONFIGURATION_DEBUG: '', + GCC_PREPROCESSOR_DEFINITIONS: 'COCOAPODS=1', + }), + ).toBe('Debug'); + }); + + test('selects Debug when POD_CONFIGURATION_DEBUG is YES', () => { + expect( + resolve({ + CONFIGURATION: 'Staging', + POD_CONFIGURATION_DEBUG: 'YES', + GCC_PREPROCESSOR_DEFINITIONS: 'COCOAPODS=1', + }), + ).toBe('Debug'); + }); + + test('selects Debug when DEBUG=1 is in GCC_PREPROCESSOR_DEFINITIONS', () => { + expect( + resolve({ + CONFIGURATION: 'Custom', + POD_CONFIGURATION_DEBUG: '', + GCC_PREPROCESSOR_DEFINITIONS: 'COCOAPODS=1 DEBUG=1', + }), + ).toBe('Debug'); + }); + + test('keeps Release when hermes-engine Debug lacks DEBUG=1 (static CocoaPods shape)', () => { + // Shared helper must not treat missing DEBUG=1 as Debug by itself — + // CONFIGURATION / POD_CONFIGURATION_DEBUG carry that signal. + // hermes-engine.podspec may OR HERMES_ENABLE_DEBUGGER=1 after sourcing. + expect( + resolve({ + CONFIGURATION: 'Release', + POD_CONFIGURATION_DEBUG: '', + GCC_PREPROCESSOR_DEFINITIONS: 'COCOAPODS=1 HERMES_ENABLE_DEBUGGER=1', + }), + ).toBe('Release'); + }); +}); diff --git a/packages/react-native/scripts/xcode/resolve-prebuilt-configuration.sh b/packages/react-native/scripts/xcode/resolve-prebuilt-configuration.sh new file mode 100755 index 000000000000..01ad3cb25699 --- /dev/null +++ b/packages/react-native/scripts/xcode/resolve-prebuilt-configuration.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# 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. + +# Resolve Debug vs Release for prebuilt iOS tarball swap script phases +# (hermes-engine, React-Core-prebuilt, ReactNativeDependencies). +# +# Prefer Xcode / CocoaPods configuration signals over grepping +# GCC_PREPROCESSOR_DEFINITIONS for DEBUG=1 alone. That def is often missing +# on hermes-engine under static CocoaPods, which incorrectly kept Release +# hermesvm while React-hermes compiled with HERMES_ENABLE_DEBUGGER=1 +# (undefined facebook::hermes::cdp::CDPDebugAPI::* at link). +# See https://github.com/facebook/react-native/issues/59116 +# +# Usage (source from a podspec script phase after with-environment.sh): +# . "$REACT_NATIVE_PATH/scripts/xcode/resolve-prebuilt-configuration.sh" +# # sets CONFIG to "Debug" or "Release" +# +# Usage (CLI / unit tests): +# ./resolve-prebuilt-configuration.sh # prints Debug|Release + +CONFIG="Release" +if [ "${CONFIGURATION:-}" = "Debug" ] || \ + [ "${POD_CONFIGURATION_DEBUG:-}" = "YES" ] || \ + echo "${GCC_PREPROCESSOR_DEFINITIONS:-}" | grep -q "DEBUG=1"; then + CONFIG="Debug" +fi + +# When executed directly (not sourced), print CONFIG for tests/CLI. +# When sourced, $0 is typically the parent shell, so we only export CONFIG. +case "${0##*/}" in + resolve-prebuilt-configuration.sh) + printf '%s\n' "$CONFIG" + ;; +esac diff --git a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec index b6775c1dbfaa..821d1b99f2aa 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec +++ b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec @@ -94,9 +94,11 @@ Pod::Spec.new do |spec| :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 + . "$REACT_NATIVE_PATH/scripts/xcode/resolve-prebuilt-configuration.sh" + # Hermes-only: React-hermes may enable CDP via HERMES_ENABLE_DEBUGGER + # without DEBUG=1 on this target (static CocoaPods). Keep that signal + # out of the shared helper — it is not meaningful for RNCore / RNDeps. + if [ "$CONFIG" != "Debug" ] && echo "${GCC_PREPROCESSOR_DEFINITIONS:-}" | grep -q "HERMES_ENABLE_DEBUGGER=1"; then CONFIG="Debug" fi diff --git a/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec b/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec index a006f2c1e4ca..a86fad539fd8 100644 --- a/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec +++ b/packages/react-native/third-party-podspecs/ReactNativeDependencies.podspec @@ -76,11 +76,7 @@ Pod::Spec.new do |spec| :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 + . "$REACT_NATIVE_PATH/scripts/xcode/resolve-prebuilt-configuration.sh" "$NODE_BINARY" "$REACT_NATIVE_PATH/third-party-podspecs/replace_dependencies_version.js" -c "$CONFIG" -r "#{version}" -p "$PODS_ROOT" EOS