Skip to content

Commit ea38382

Browse files
huntiemeta-codesync[bot]
authored andcommitted
Fix REACT_NATIVE_PATH resolution when Pods/ is a symlink (facebook#56453)
Summary: Pull Request resolved: facebook#56453 **Problem** On Meta's virtual filesystem, we've started making `Pods/` a symlink for performance reasons. The `REACT_NATIVE_PATH` Xcode build setting was constructed as `${PODS_ROOT}/../<relative_path>`, assuming that `${PODS_ROOT}/..` equals the Podfile directory (`ios/`). When `Pods/` is a symlink to a different filesystem depth, Xcode resolves `${PODS_ROOT}` to the physical target, and `..` traverses the wrong tree — landing one directory too high and producing a nonexistent path. This broke four Xcode script phases at build time: `hermes-engine`, `ReactNativeDependencies`, `React-Core-prebuilt`, and `ReactCodegen`. **Root cause** The `$PODS_ROOT/..` idiom appears in four independent locations across Ruby, JavaScript, and shell layers. Each assumes the Pods directory is a direct child of the Podfile directory, which breaks when Pods/ is a symlink to a different filesystem depth. **Fix** All four sites are patched with the same approach: a new `PODFILE_DIR` Xcode build setting (set to the absolute Podfile directory path at pod install time) replaces the broken `$PODS_ROOT/..` derivation, with a fallback to the old behavior for backward compatibility. **Changed files** - **react_native_pods.rb** — Constructs the `REACT_NATIVE_PATH` build setting in `react_native_post_install`. Now resolves both the Pods directory and the react-native path to their real (physical) filesystem locations via `Pathname#realpath` before computing the relative path. Also adds the new `PODFILE_DIR` build setting. - **with-environment.sh** — Sourced by script phases to set up `NODE_BINARY`. Located `.xcode.env` via `$PODS_ROOT/../.xcode.env`. Now uses `$PODFILE_DIR` with fallback. - **script_phases.rb** — Ruby ERB template that generates shell scripts for codegen build phases. Used `pushd "$PODS_ROOT/../"` to derive the Podfile directory. Now uses `$PODFILE_DIR` with fallback. - **generateReactCodegenPodspec.js** — JavaScript template that generates the ReactCodegen.podspec "Generate Specs" script phase. Had its own hardcoded `pushd "$PODS_ROOT/../"`. Now uses `$PODFILE_DIR` with fallback. Reviewed By: cipolleschi Differential Revision: D100830088 fbshipit-source-id: b92e83e8491b9e947245e149f0fe8f4b3b81c2ad
1 parent cdfed83 commit ea38382

4 files changed

Lines changed: 35 additions & 8 deletions

File tree

packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,16 @@ function codegenScripts(appPath /*: string */, baseOutputPath /*: string */) {
8282
baseOutputPath,
8383
REACT_NATIVE_PACKAGE_ROOT_FOLDER,
8484
);
85+
// Use PODFILE_DIR (set by react_native_post_install) to locate the Podfile
86+
// directory. PODS_ROOT/.. does not work when Pods/ is a symlink.
8587
return `<<-SCRIPT
86-
pushd "$PODS_ROOT/../" > /dev/null
87-
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
88-
popd >/dev/null
88+
if [ -n "$PODFILE_DIR" ]; then
89+
RCT_SCRIPT_POD_INSTALLATION_ROOT="$PODFILE_DIR"
90+
else
91+
pushd "$PODS_ROOT/../" > /dev/null
92+
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
93+
popd >/dev/null
94+
fi
8995
9096
export RCT_SCRIPT_RN_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeReactNativeRootFolder}"
9197
export RCT_SCRIPT_APP_PATH="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeAppPath.length === 0 ? '.' : relativeAppPath}"

packages/react-native/scripts/react_native_pods.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,16 @@ def react_native_post_install(
531531
ReactNativePodsUtils.fix_library_search_paths(installer)
532532
ReactNativePodsUtils.update_search_paths(installer)
533533
ReactNativePodsUtils.set_build_setting(installer, build_setting: "USE_HERMES", value: use_hermes())
534-
ReactNativePodsUtils.set_build_setting(installer, build_setting: "REACT_NATIVE_PATH", value: File.join("${PODS_ROOT}", "..", react_native_path))
534+
# Compute REACT_NATIVE_PATH relative to PODS_ROOT using real (physical)
535+
# paths, so the relative traversal is correct even when Pods/ is a symlink.
536+
pods_dir_real = Pathname.new(Pod::Config.instance.sandbox_root.to_s).realpath
537+
rn_absolute = File.expand_path(react_native_path, Pod::Config.instance.installation_root.to_s)
538+
rn_real = Pathname.new(rn_absolute).realpath
539+
rn_relative_to_pods = rn_real.relative_path_from(pods_dir_real)
540+
ReactNativePodsUtils.set_build_setting(installer, build_setting: "REACT_NATIVE_PATH", value: File.join("${PODS_ROOT}", rn_relative_to_pods.to_s))
541+
# Store the Podfile directory as a build setting so that shell scripts can
542+
# locate it without relying on PODS_ROOT/.. (breaks when Pods/ is a symlink).
543+
ReactNativePodsUtils.set_build_setting(installer, build_setting: "PODFILE_DIR", value: Pod::Config.instance.installation_root.to_s)
535544
ReactNativePodsUtils.set_build_setting(installer, build_setting: "SWIFT_ACTIVE_COMPILATION_CONDITIONS", value: ['$(inherited)', 'DEBUG'], config_name: "Debug")
536545

537546
if (ENV['RCT_REMOVE_LEGACY_ARCH'] == '1')

packages/react-native/scripts/react_native_pods_utils/script_phases.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ def get_script_phases_no_codegen_discovery(options)
3535

3636
def get_script_template(react_native_path, export_vars={})
3737
template =<<~EOS
38-
pushd "$PODS_ROOT/../" > /dev/null
39-
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
40-
popd >/dev/null
38+
# Use PODFILE_DIR (set by react_native_post_install) to locate the
39+
# Podfile directory. PODS_ROOT/.. does not work when Pods/ is a symlink.
40+
if [ -n "$PODFILE_DIR" ]; then
41+
RCT_SCRIPT_POD_INSTALLATION_ROOT="$PODFILE_DIR"
42+
else
43+
pushd "$PODS_ROOT/../" > /dev/null
44+
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
45+
popd >/dev/null
46+
fi
4147
<% export_vars.each do |(varname, value)| %>
4248
export <%= varname -%>=<%= value -%>
4349
<% end %>

packages/react-native/scripts/xcode/with-environment.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ NODE_BINARY=$(command -v node || echo "")
1717
export NODE_BINARY
1818

1919
# Override the default with the global environment
20-
ENV_PATH="$PODS_ROOT/../.xcode.env"
20+
# Use PODFILE_DIR (set by react_native_post_install) to locate .xcode.env.
21+
# PODS_ROOT/.. does not work when Pods/ is a symlink.
22+
if [ -n "$PODFILE_DIR" ]; then
23+
ENV_PATH="$PODFILE_DIR/.xcode.env"
24+
else
25+
ENV_PATH="$PODS_ROOT/../.xcode.env"
26+
fi
2127
if [ -f "$ENV_PATH" ]; then
2228
source "$ENV_PATH"
2329
fi

0 commit comments

Comments
 (0)