Android NDK:为相同的 abi 提供库变体

Android NDK: Providing library variants for the same abi

我正在寻找开发和打包具有不同编译设置但针对相同 ABI 的库的不同变体的最佳方法,然后在运行时选择最适合的。更具体地说,我想要一个 NEON 和非 NEON armeabi-v7a 版本。

本机库有一个 public 第三方 link 的 C 接口。他们似乎需要 link 到其中一个变体以防止 link 错误,但我想在运行时加载替代变体,如果它更适合设备,并且有运行时加载器做正确的搬迁。

据我目前所见,我似乎需要为两个变体提供相同的文件名,因此需要将它们放在不同的文件夹中。 abi 文件夹下的子文件夹似乎不会被包安装过程复制,因此该方法不起作用。到目前为止,我所看到的最佳建议是手动将一个变体从 res 文件夹复制到已知设备路径,并使用完整路径调用 System.loadLibrary()。参考:https://groups.google.com/forum/#!topic/android-ndk/zu_dmcmUlMo

  1. 这仍然是 best/recommended 方法吗?
  2. 这将如何与在非 arm 设备上完成的二进制翻译交互? (虽然我可以提供 x86 构建,但某些第三方可能会将其排除在他们的 apk 之外)。

我假设 cpu使用二进制翻译的设备上的功能不会将 cpu 系列报告为 ARM,因此我建议的解决方案是在正常方式(我猜这将得到二进制翻译),并在 res/raw 中发布支持 NEON 的库。然后在运行时,如果 cpufeatures 报告带有 NEON 支持的 ARM CPU,则复制该库并使用完整路径调用 loadLibrary。任何人都可以看出这种方法有什么问题吗?

如果您明确想要一个库的两个不同版本,那么是的,这可能是最好的折衷方案。

首先 - 请注意,许多可以使用 NEON 的库都可以使用启用运行时的那些部分来构建,这样您就可以拥有一个正常的 ARMv7 构建,它不严格要求 NEON,但可以在运行时启用这些代码路径,如果检测到 - 例如libav/FFmpeg 这样做,许多其他类似的库也是如此。这允许您拥有一个 ARMv7 二进制文件,在适用的情况下充分利用 NEON,同时仍然可以在少数没有 NEON 的 ARMv7 设备上运行。

如果您正在尝试使用编译器自动向量化,或者如果这是一个 NEON 例程不容易局限于运行时启用的受限部分的库(或者希望通过构建整个库来获得额外的性能启用 NEON),您的方法听起来很明智。

请记住,您希望至少有一个打包的本机库 "normally"(您似乎有,但在 中这一直是个问题)。安装时,安装程​​序会选择最匹配的捆绑架构,并仅从该架构中提取库,并以该模式运行该过程。在具有多个 ABI(32 位和 64 位)的设备上,这是必不可少的,因为如果进程以不同的模式启动,一旦您尝试以不同的形式加载库,切换模式就太晚了。

在模拟 ARM 二进制文件的 x86 设备上,如果进程在 ARM 模式下 运行,至少 cpufeatures 库将 return ARM。如果您使用系统属性来查找主要和次要 ABI,您将不知道当前进程正在使用它们中的哪一个。

编辑:具有二进制翻译的 x86 设备实际上似乎能够加载 armeabi 库,即使同一进程也已经加载了一些捆绑的 x86 库。所以显然这种翻译是在每个库的基础上完成的,不像 32 位和 64 位,在启动时为进程选择某种模式,这不包括加载其他变体的任何库。