Skip to content

feat: allow extending the list of libs kept out of the AAR - #442

Merged
hurali97 merged 2 commits into
callstack:mainfrom
janicduplessis:feat/configurable-ignore-embedded-libs
Aug 7, 2026
Merged

feat: allow extending the list of libs kept out of the AAR#442
hurali97 merged 2 commits into
callstack:mainfrom
janicduplessis:feat/configurable-ignore-embedded-libs

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Problem

The plugin embeds .so files from the app's dependencies into the AAR, and separately declares those same dependencies in the published Gradle module metadata. When the host App resolves one of them from Maven it ends up with the library twice — once inside the AAR, once from the Maven artifact — and packaging fails:

> 2 files found with path 'lib/arm64-v8a/libdatadog-ndk.so' from inputs:
   - .../transformed/<sdk>-release/jni/arm64-v8a/libdatadog-ndk.so
   - .../transformed/dd-sdk-android-ndk-3.11.0/jni/arm64-v8a/libdatadog-ndk.so
Execution failed for task ':app:mergeReleaseNativeLibs'.

IGNORE_EMBEDDED_LIBS already exists for exactly this situation, and its comment describes it well — libs "provided by the Gradle when AAR is consumed by the host App". But it is a fixed list covering React Native's own libraries, so a project that hits this with any other dependency has no way out of it.

In our app three libraries are in that position: libdatadog-ndk.so, libopentok.so and libzstd-kmp.so — each bundled in the AAR and declared in its metadata. Datadog just happens to fail first.

Solution

Add reactBrownfield.ignoreEmbeddedLibs, appended to the built-in list:

reactBrownfield {
    ignoreEmbeddedLibs = listOf("libdatadog-ndk.so", "libopentok.so", "libzstd-kmp.so")
}

Default is empty, so behaviour is unchanged for everyone else.

A host can work around this today with packaging { jniLibs { pickFirsts += ... } }, but that still ships the duplicate into the AAR and just picks one at packaging time, and it has to be repeated by every integrator. Excluding at the source keeps the AAR correct.

Test plan

Verified against a real brownfield SDK build (Expo SDK 57 / RN 0.86, New Architecture):

  • Before: AAR contained 17 .so per ABI including the three above; host app failed at mergeReleaseNativeLibs on libdatadog-ndk.so.
  • After, with the three listed in ignoreEmbeddedLibs: AAR contains 14 .so per ABI, the three are absent, and the host app's mergeReleaseNativeLibs succeeds with no pickFirsts workaround.
  • With the option unset, the AAR is byte-for-byte what it was before.

The plugin embeds .so files from the app's dependencies into the AAR, and
separately declares those same dependencies in the published module metadata.
When a host App resolves one of them from Maven it ends up with two copies of
the library and mergeNativeLibs fails on the duplicate.

IGNORE_EMBEDDED_LIBS already covers this for React Native's own libraries, but
it is a fixed list, so any other dependency in that position has no way out.
Add reactBrownfield.ignoreEmbeddedLibs so a project can extend it.
Copilot AI lite review requested due to automatic review settings August 7, 2026 03:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Gradle extension option to let consumers exclude additional native .so files from being embedded into the produced AAR, avoiding duplicate-native-lib packaging failures when those dependencies are also declared in published module metadata.

Changes:

  • Introduces reactBrownfield.ignoreEmbeddedLibs on the plugin extension (default empty).
  • Wires the new option into ProcessAndCopyJniLibsTask and applies it alongside the existing IGNORE_EMBEDDED_LIBS filter.
  • Adds a changeset entry documenting the patch release.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/utils/Extension.kt Adds ignoreEmbeddedLibs extension property with KDoc explaining the duplicate .so issue.
gradle-plugins/react/brownfield/src/main/kotlin/com/callstack/react/brownfield/processors/JNILibsProcessor.kt Adds a task input for extra ignored libs and uses it when filtering embedded .so files.
.changeset/tidy-moons-shave.md Documents the new option as a patch changeset.

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

@janicduplessis

Copy link
Copy Markdown
Contributor Author

Good catch on the KDoc link — IGNORE_EMBEDDED_LIBS lives in com.callstack.react.brownfield.processors and isn't imported here, so it wouldn't have resolved. Fully qualified it.

@hurali97 hurali97 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for fixing this 🚀

@hurali97
hurali97 merged commit 7898f8a into callstack:main Aug 7, 2026
10 checks passed
@janicduplessis
janicduplessis deleted the feat/configurable-ignore-embedded-libs branch August 7, 2026 08:24
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.

3 participants