Skip to content

Generate PackageList per variant so build-type dependencies resolve - #59739

Open
NemesisDevX wants to merge 2 commits into
react:mainfrom
NemesisDevX:fix/59692-variant-package-list
Open

NemesisDevX wants to merge 2 commits into
react:mainfrom
NemesisDevX:fix/59692-variant-package-list

Conversation

@NemesisDevX

Copy link
Copy Markdown

Summary:

Fixes #59692

A dependency that declares platforms.android.buildTypes (e.g. ['debug']) is only added to the matching ${buildType}Implementation configuration(s) by ReactExtension. However, generateAutolinkingPackageList produced a single shared PackageList.java — containing every autolinked package — and that directory was attached to all variants. A debug-only package class was therefore referenced from the release PackageList.java, where the dependency is correctly absent from the compile classpath, so :app:compileReleaseJavaWithJavac failed with package <debug-only package> does not exist.

PackageList.java is now generated once per variant:

  • GeneratePackageListTask gains an optional buildType input; a dependency is emitted when its buildTypes list is empty (shared) or contains the variant's build type — mirroring exactly the classpath scoping that ${buildType}Implementation already applies.
  • ReactPlugin registers a generateAutolinkingPackageList<Variant> task inside onVariants, writing to generated/autolinking/src/<variant>/java and attaching that directory only to its own variant. The generateAutolinkingPackageList task name is kept as a lifecycle aggregator over the per-variant tasks.
  • The variant-agnostic ReactNativeApplicationEntryPoint.java moves to generated/autolinking/src/common/java. Reusing the old src/main/java path would have re-attached stale PackageList.java files generated by older React Native versions (persistent build/ dirs), producing duplicate-class errors on upgrade — the new path makes that impossible by construction.

Backward compatible: no buildType set → previous include-all behavior; the CLI/CLI-invoked task name is unchanged; unrelated variants are untouched.

Changelog:

[ANDROID] [FIXED] - Generate PackageList per variant so dependencies restricted to specific build types are not referenced from variants that lack them on the classpath

Test Plan:

Unit tests (packages/gradle-plugin, ./gradlew :react-native-gradle-plugin:test --tests "*GeneratePackageListTaskTest*"):

  • 5 new filterAndroidPackages cases: matching build type included, non-matching excluded, multi-entry buildTypes matched on any entry, shared (buildTypes: []) included for every build type, unset build type preserves legacy include-all behavior — all pass, along with the pre-existing suite. (ReactPluginTest, ReactExtensionTest, GenerateEntryPointTaskTest also green.)

Reproduced on the issue's own reproducer (https://github.com/YevheniiKotyrlo/rn-build-types-package-list), Gradle 9.4.1 / AGP 9, Windows 11, JDK 17 toolchain, patching the included-build plugin in node_modules/@react-native/gradle-plugin:

Before — ./gradlew :app:compileDebugJavaWithJavac :app:compileReleaseJavaWithJavac --continue:

  • :app:compileDebugJavaWithJavac ✅
  • :app:compileReleaseJavaWithJavac ❌ PackageList.java:61: error: package com.debugonlylibrary does not exist — exact failure from the issue.

After, same command with the stale src/main/java outputs still on disk:

  • Both compile tasks ✅ (BUILD SUCCESSFUL).
  • src/debug/java/.../PackageList.java lists SafeAreaContextPackage + DebugOnlyPackage; src/release/java/... lists only SafeAreaContextPackage; src/debugOptimized/java/... correctly excludes it too (matching debugOptimizedImplementation classpath).
  • Reverse direction verified e2e: flipping the module to buildTypes: ['release'] removes it from debug/debugOptimized lists and includes it in release; both compiles still green.
  • Upgrade path verified: leftover src/main/java/.../PackageList.java from the previous plugin version no longer causes a duplicate-class failure because that directory is no longer a source root.

Incremental: re-running the same command → all tasks UP-TO-DATE.
Configuration cache: first run stores the entry with no problems; second run reports Reusing configuration cache / Configuration cache entry reused with all generation tasks up-to-date.

Formatting: ktfmt 0.59.0 (the jar CI runs via yarn format-check-kotlin) --check passes on all touched files.

Not run: full assembleDebug/assembleRelease APK builds (the issue's own repro command is the javac compile tasks, which were exercised), iOS/macOS builds (Android-only change), and the repo's other test jobs — relying on CI for those.


Disclosure: this change was developed with AI-agent assistance (implementation + test authoring); all listed verification commands were actually executed and their outputs are reported as observed.

Dependencies declaring platforms.android.buildTypes are added to the
matching ${buildType}Implementation configurations only, but
generateAutolinkingPackageList produced a single shared PackageList.java
attached to every variant. A debug-only package was therefore listed in
release builds, where the class is not on the compile classpath, and
release compilation failed.

PackageList.java is now generated once per variant into
generated/autolinking/src/<variant>/java, added as a source directory
only to that variant, and filtered so a dependency is listed when its
buildTypes list is empty or contains the variant's build type. The
generateAutolinkingPackageList task remains as a lifecycle aggregator,
and the variant-agnostic entry point file moves to
generated/autolinking/src/common/java so stale PackageList outputs left
behind by older versions can never be picked up as sources again.

Fixes react#59692
@meta-cla

meta-cla Bot commented Nov 1, 2026

Copy link
Copy Markdown

Hi @NemesisDevX!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

Honors dependencyConfiguration overrides in addition to buildTypes: a
dependency is now listed only when one of its resolved Gradle
configurations (as applied by getGradleDependenciesToApply) is on the
variant's actual compile classpath, read from the configuration's
transitive extendsFrom closure.

This branch has not been deployed

No deployments
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.

Android autolinking: a library limited to debug by buildTypes is still in the release variant's PackageList.java, so the release build does not compile

1 participant