首页 > 解决方案 > 我如何告诉 Gradle 仅从特定的 aar 中选择给定的本机库

问题描述

我正在尝试构建一个依赖于依赖项的应用程序,这些依赖项引入了许多版本的 libc++_shared.so;通常

packagingOptions {
  pickFirst 'lib/armeabi-v7a/libc++_shared.so'
  pickFirst 'lib/arm64-v8a/libc++_shared.so'
}

dance 允许构建成功,但我有一个运行时崩溃,因为某些 libc++_shared 版本(显然包括 Gradle 首先看到并选择的版本)是在没有异常处理支持的情况下编译的,而其他依赖项需要本机异常处理。我相信是这种情况,因为当加载需要异常处理的本机库时,我一直看到 java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__sfp_handle_exceptions" 在运行时崩溃。

我是其中一个 aar 的作者,我知道它的 libc++_shared 具有异常处理功能,因此我试图强制 Gradle 从该已知 aar 中专门选择 libc++_shared。在看到我要从中提取的 aar 的缓存版本在 jni/abi/ 下具有 libc++_shared 后,我尝试了以下操作

exclude 'lib/armeabi-v7a/libc++_shared.so'
exclude 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'com/mycompany/*/jni/armeabi-v7a/libc++_shared.so'
pickFirst 'com/mycompany/*/jni/arm64-v8a/libc++_shared.so'

并且

exclude 'lib/armeabi-v7a/libc++_shared.so'
exclude 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'com.mycompany/*/jni/armeabi-v7a/libc++_shared.so'
pickFirst 'com.mycompany/*/jni/arm64-v8a/libc++_shared.so'

以及上面使用 aar 模块名称 mymodule-1.1.1 代替通配符的两个排列。不幸的是,这些都导致最终的 apk 中没有包含 libc++_shared.so 的版本,所以我猜我要么有错误的 aar 路径语法,要么 pickFirst 不能用于此目的。

问题:

  1. 有没有办法获取 Gradle 正在考虑打包的文件路径列表,所以我不必猜测在 Gradle 的 PackagingOptions 正在查看时 aar 名称和结构是什么?
  2. 如何告诉 Gradle 仅从给定的 aar 打包特定的 libc++_shared?

编辑:不是一个通用的解决方案,但我找到了针对这种特定情况的解决方法——当我在我的 com.mycompany:mainsdk 依赖项中启用传递依赖项以及打包异常处理 libc++_shared 的本机模块时,首先出现了问题变成只有及物的;以前我一直直接拉下所有 com.mycompany 模块,因为它们的 pom 文件没有传递的 dep 信息,但在添加该信息后,我认为我只需要单个 com.mycompany:mainsdk 依赖项。这个假设名义上是正确的,但显然具有使 libc++_shared 版本与 com 打包在一起的副作用。mycompany 本机 deps 要么出现在 Gradle 打包序列的后期,要么被视为较低优先级,因此 pickFirst 始终选择打包 libc++_shared 而不进行异常处理的另一个直接依赖项。我尝试将 com.mycompany 本机 dep 模块之一作为直接 dep 带回,突然 Gradle 总是从他那里选择 libc++_shared!不知道它是否重要,但是我添加回来的本机 dep 出现在拉入 libc++_shared 而没有异常处理的那个之前。好的 ol' Gradle 奥秘...

标签: androidgradleandroid-gradle-plugin

解决方案


推荐阅读