Codegen: app codegenConfig with no spec files emits "${PODS_ROOT}/.." as Generate Specs input and causes an Xcode dependency cycle

Open Beginner friendly
#58,621 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
1/5
Estimated time
Under an hour
Newbie friendliness
92/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
javascript, react-native

Research direction

Start in scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js, especially getInputFiles(), and reproduce the app-level codegenConfig case with an empty jsSrcsDir. Inspect the generated ReactCodegen.podspec and confirm that the Generate Specs input_files list is empty rather than containing the ios directory; then verify the Xcode dependency cycle no longer occurs.

Written by the indexing model from the issue text.

Description

Needs: Author Feedback Needs: Repro
Description

scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.jsgetInputFiles() builds the Generate Specs script phase input_files from a find over the app's codegenConfig.jsSrcsDir. When that directory contains no Native*.{js,ts} / *NativeComponent.{js,ts} files, execSync(find …) returns an empty string, ''.trim().split('\n') is [''], and the single empty path is mapped to:

'input_files' => ["${PODS_ROOT}/.."]

i.e. the whole ios/ directory. Xcode then sees that the Generate Specs phase of ReactCodegen depends on files produced by other targets' script phases in that directory (in an Expo project: the app target's [Expo] Configure project phase, which writes Pods/Target Support Files/…/ExpoModulesProvider.swift) and fails:

error: Cycle in dependencies between targets 'Callingx' and 'TurnoHosts'; building could produce unreliable results.
Cycle path: Callingx → ReactCodegen → TurnoHosts → Callingx
→ Target 'Callingx' has an explicit dependency on Target 'ReactCodegen'
○ That command depends on command in Target 'ReactCodegen': script phase “[CP-User] Generate Specs”
→ That command depends on command in Target 'TurnoHosts': script phase “[Expo] Configure project”

An app-level codegenConfig with no spec files is a legitimate setup: it is the documented way to declare ios.modulesConformingToProtocol (e.g. an RCTImageURLLoader) from the app when a dependency cannot.

Steps to reproduce
  1. In an app's package.json add
    "codegenConfig": { "name": "AppSpecs", "type": "modules", "jsSrcsDir": "src/config", "ios": { "modulesConformingToProtocol": { "RCTImageURLLoader": ["SomeLoader"] } } }
    
    where src/config exists but has no spec files.
  2. pod install
  3. Inspect ios/build/generated/ios/ReactCodegen/ReactCodegen.podspec'input_files' => ["${PODS_ROOT}/.."].
  4. Build in Xcode → dependency cycle error above (seen with Expo SDK 57 projects; any other script phase writing under ios/ triggers it too).
Fix

Filter the empty entry:

   const list = String(execSync(findCommand))
     .trim()
     .split('\n')
+    .filter(Boolean)
     .sort()

With that, input_files is [] (same as projects without an app codegenConfig) and the build succeeds.

React Native Version

0.86.3

Affected Platforms

Build - MacOS, Runtime - iOS

Dominant language
C++
Stars
127k
Forks
25.3k
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from react/react-native

All issues in react/react-native

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.