From e8edb3f34a9f703b6e3b2b33615ef756673f0c07 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Fri, 8 May 2026 14:37:03 +0200 Subject: [PATCH 1/3] Make PODFILE_DIR build setting portable across machines Writing the Podfile installation_root as an absolute path bakes the contributor's machine path into project.pbxproj, which then ships in git diffs and breaks teammates who clone to a different location. Set PODFILE_DIR per-project using Xcode variable substitution instead: $(SRCROOT) for user projects (whose SRCROOT is the Podfile dir) and $(SRCROOT)/.. for the Pods project. The resolved value is identical at build time but the persisted setting is now machine-independent. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/react-native/scripts/react_native_pods.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 3296a20bbd55..24ec01c196f9 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -540,7 +540,18 @@ def react_native_post_install( ReactNativePodsUtils.set_build_setting(installer, build_setting: "REACT_NATIVE_PATH", value: File.join("${PODS_ROOT}", rn_relative_to_pods.to_s)) # Store the Podfile directory as a build setting so that shell scripts can # locate it without relying on PODS_ROOT/.. (breaks when Pods/ is a symlink). - ReactNativePodsUtils.set_build_setting(installer, build_setting: "PODFILE_DIR", value: Pod::Config.instance.installation_root.to_s) + # Use Xcode variable substitution per-project so the value persisted in + # project.pbxproj is portable across machines. + installer.aggregate_targets.map(&:user_project).uniq(&:path).each do |user_project| + user_project.build_configurations.each do |config| + config.build_settings['PODFILE_DIR'] = '$(SRCROOT)' + end + user_project.save + end + installer.pods_project.build_configurations.each do |config| + config.build_settings['PODFILE_DIR'] = '$(SRCROOT)/..' + end + installer.pods_project.save ReactNativePodsUtils.set_build_setting(installer, build_setting: "SWIFT_ACTIVE_COMPILATION_CONDITIONS", value: ['$(inherited)', 'DEBUG'], config_name: "Debug") if (ENV['RCT_REMOVE_LEGACY_ARCH'] == '1') From 5eed812292ec4ae8f53d2b23abbf5b354bedbb7d Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Fri, 8 May 2026 14:42:38 +0200 Subject: [PATCH 2/3] update comment --- packages/react-native/scripts/react_native_pods.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 24ec01c196f9..a32bb5b7b84e 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -539,9 +539,11 @@ def react_native_post_install( rn_relative_to_pods = rn_real.relative_path_from(pods_dir_real) ReactNativePodsUtils.set_build_setting(installer, build_setting: "REACT_NATIVE_PATH", value: File.join("${PODS_ROOT}", rn_relative_to_pods.to_s)) # Store the Podfile directory as a build setting so that shell scripts can - # locate it without relying on PODS_ROOT/.. (breaks when Pods/ is a symlink). - # Use Xcode variable substitution per-project so the value persisted in - # project.pbxproj is portable across machines. + # locate it without hardcoding an absolute path. Use Xcode variable + # substitution per-project so the value persisted in project.pbxproj is + # portable across machines: $(SRCROOT) is the Podfile dir for user projects + # (also avoids the PODS_ROOT/.. traversal that breaks when Pods/ is a + # symlink), and $(SRCROOT)/.. for the Pods project. installer.aggregate_targets.map(&:user_project).uniq(&:path).each do |user_project| user_project.build_configurations.each do |config| config.build_settings['PODFILE_DIR'] = '$(SRCROOT)' From a76ac6e1739329c33aa258143009558ed93af892 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Fri, 8 May 2026 14:33:16 +0200 Subject: [PATCH 3/3] Resolve appPath in getInputFiles so "/Pods/" filter doesn't drop xcodeproj results When appPath contains a "Pods/.." segment, every find result inherits that prefix and gets filtered out by the "/Pods/" exclusion. Normalize via path.resolve before invoking find so the segment is collapsed up front. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../generateReactCodegenPodspec.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js index 70221d3c988a..00e0da3d96df 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js @@ -49,8 +49,13 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) { return '[]'; } + // Normalize appPath so any "Pods/.." segment is collapsed before find runs. + // Otherwise every find result inherits the search-root prefix containing + // "/Pods/" and gets dropped by the exclusion filter below. + const resolvedAppPath = path.resolve(appPath); + const xcodeproj = String( - execSync(`find ${appPath} -type d -name "*.xcodeproj"`), + execSync(`find ${resolvedAppPath} -type d -name "*.xcodeproj"`), ) .trim() .split('\n') @@ -61,12 +66,12 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) { )[0]; if (!xcodeproj) { throw new Error( - `Cannot find .xcodeproj file inside ${appPath}. This is required to determine codegen spec paths relative to native project.`, + `Cannot find .xcodeproj file inside ${resolvedAppPath}. This is required to determine codegen spec paths relative to native project.`, ); } const jsFiles = '-name "Native*.js" -or -name "*NativeComponent.js"'; const tsFiles = '-name "Native*.ts" -or -name "*NativeComponent.ts"'; - const findCommand = `find ${path.join(appPath, jsSrcsDir)} -type f -not -path "*/__mocks__/*" -and \\( ${jsFiles} -or ${tsFiles} \\)`; + const findCommand = `find ${path.join(resolvedAppPath, jsSrcsDir)} -type f -not -path "*/__mocks__/*" -and \\( ${jsFiles} -or ${tsFiles} \\)`; const list = String(execSync(findCommand)) .trim() .split('\n')