Skip to content

Comments

Fix package exclusion by moving App Clip target to top level#84

Open
trentrand wants to merge 3 commits intobndkt:mainfrom
trentrand:fix-package-exclusion
Open

Fix package exclusion by moving App Clip target to top level#84
trentrand wants to merge 3 commits intobndkt:mainfrom
trentrand:fix-package-exclusion

Conversation

@trentrand
Copy link
Contributor

@trentrand trentrand commented Feb 17, 2026

Previously, the App Clip target was generated nested inside the main app
target in the Podfile. CocoaPods treats nested targets as inheriting all
pods from their parent, which caused excludedPackages to be completely
ineffective — excluded packages were still installed and linked.

This change moves the App Clip target to the top level as a sibling of the
main target. With no dependency inheritance, use_expo_modules!(exclude:)
works correctly and excluded packages are fully absent from the App Clip
build.

Also clarifies in the README that excludedPackages takes npm package names.

Fixes #81, #79

Previously, the App Clip target was generated nested inside the main app
target in the Podfile. This caused it to inherit all pods from the parent,
rendering `excludedPackages` completely ineffective.

This change moves the App Clip target to the top level as a sibling of the
main target, preventing implicit dependency inheritance.

However, even with the target un-nested, CocoaPods still emits linker flags
for all resolved pods into the generated `.xcconfig` files. This is
especially problematic under new architecture + static frameworks, where
Codegen headers are expected to exist for any linked package — causing
"file not found" build failures.

To address this, a `post_install` hook is injected that:
1. Removes excluded packages from the App Clip target's dependency graph
2. Strips all corresponding linker flags (`-l"Pkg"`, `-framework "Pkg"`)
   directly from the generated xcconfig files via `Xcodeproj::Config`

This two-pronged approach ensures excluded packages are absent from both
the build graph and the linker invocation, regardless of project settings.

Fixes bndkt#81, bndkt#79
Copilot AI review requested due to automatic review settings February 17, 2026 22:42
@trentrand
Copy link
Contributor Author

trentrand commented Feb 17, 2026

@nathan-ahn, one last change (hopefully) to the package to fix the excludedPackages feature.

This one fixes @changhwan0813's issue #81 and my own #71. Both are essentially the same issue.

A lot of the line changes are just indentation to get the resulting Podfile correctly formatted, so make sure to turn on 'Hide whitespace':
Screenshot 2026-02-17 at 3 45 08 PM


Without this change, on version 0.7.1, using excludedPackages results in a build failure. E.g.
Screenshot 2026-02-17 at 3 50 31 PM

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the Expo config plugin’s Podfile generation to make the App Clip target a top-level sibling (so excludedPackages can take effect) and adds a post_install patch intended to remove excluded pods and strip their linker flags from generated .xcconfig files.

Changes:

  • Move the generated App Clip target ... do block to be inserted at the Podfile top level (anchored after prepare_react_native_project!), avoiding nested-target pod inheritance.
  • Add a post_install injection that attempts to remove excluded dependencies from the App Clip Pods target and strip matching entries from OTHER_LDFLAGS in xcconfig files.
  • Adjust the App Clip autolinking command and related Podfile generation logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +50 to +56
# \`react-native-app-clip\` resolves to react-native-app-clip/build/index.js
clip_command = [
'node',
'--no-warnings',
'--eval',
'require(require.resolve(\\'react-native-app-clip\\')+\\'/../../plugin/build/cliPlugin.js\\').run(' + json + ', [])'
]
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clip_command now calls cliPlugin.run(..., []), which prevents cliPlugin.ts from deleting excluded packages from the autolinking config (it deletes keys based on the exclude array). This looks like a regression: excludedPackages will no longer be excluded from use_native_modules! resolution for the App Clip target. Pass the actual excluded package list through to the CLI plugin again (and ensure it stays in sync with excludedPackages).

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@trentrand trentrand Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing the exclude list to cliPlugin is what originally caused #79 — when excluded from use_native_modules!, Codegen does not generate spec headers for those packages, but the pod source files still #import them (e.g. NativeNfcManagerSpec.h), causing a compile failure under New Architecture. The [] is intentional: we keep packages in the autolinking config so Codegen generates their specs, then strip them from the linker in post_install. This is the two-pronged approach described in the PR.

@trentrand trentrand changed the title Fix package exclusion with sibling targets and xcconfig flag stripping Fix package exclusion by moving App Clip target to top level Feb 18, 2026
…esting)

Once the App Clip target is a sibling rather than nested inside the main target, `use_expo_modules!(exclude:)` fully prevents excluded packages from being installed or linked. The `post_install` hook that manually stripped OTHER_LDFLAGS was compensating for inherited linker flags that no longer exist.
@nathan-ahn
Copy link
Collaborator

@trentrand The theory here makes sense at an initial glance. It'll take me a bit to do some testing to ensure there's no regressions here. Considering the significant restructuring of the targets, I worry there may be some niche regressions. I'm going to do some local testing first today, then I'll create a beta version to use this in production over the next week.

Copy link
Collaborator

@nathan-ahn nathan-ahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my local testing, seems to be working! Here's what I've tried:

  1. Clip builds and runs on simulator
  2. Excluding a required native package (expo-image) causes the Clip to break (as expected)

Just one comment for a cleaner Podfile for future maintainability. Once that's sorted, I'll merge this into a beta version branch and start testing in TestFlight and production.

);
}

podfileContent = mergeContents({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the App Clip target is a sibling, can we move it to the end of the Podfile rather than being above the main app? This'll be easier for future maintainability in case the anchor disappears in a future Expo version (and remove the requirement for Expo 53+ project structure). We use this approach in react-native-widget-extension and it works quite well for sibling targets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

excludedPackages not working due to nested Podfile target

2 participants