android 二进制文件中 .so 文件的名称冲突

name conflicts of .so file in android binary

我正在将 cc_library 链接到 android_binary 并遇到命名问题。谁能告诉我怎么解决?

cc_library:

cc_library(
    name = "native_library",
    srcs = glob(["libs/**/*.so"])
)

libs目录内容:

libs
├── armeabi
│   ├── libSound.so
│   ├── libSec.so
│   ├── libWatch.so
│   └── libTec.so
├── armeabi-v7a
│   ├── libSound.so
│   ├── libSec.so
│   └── libWatch.so
├── x86
│   ├── libSound.so
│   ├── libSec.so
│   ├── libWatch.so
│   └── libTec.so
|—— other jars

并且错误信息是这样的:

ERROR: /the/path/to/BUILD:10:1: in android_binary rule //:debug_apk: Each library in the transitive closure must have a unique basename to avoid name collisions when packaged into an apk, but two libraries have the basename 'libSound.so': libs/armeabi/libSound.so and libs/armeabi-v7a/libSound.so.
...

我可能是错的,但这是 apk 布局的限制,所以恐怕你不能在胖 apk 中包含那个命名的库。将库重命名为 libSound-armeabi.so 等是否适合您?

另一种方法利用了 android_binary 的 --fat_apk_cpu 标志并且不需要重命名您的库:

android_binary 将为 --fat_apk_cpu 指定的每个架构构建每个 cc_library 一次。 --fat_apk_cpu 的默认值只是 armeabi-v7a。这被称为 "Android split transition"。当它构建每个 cc_library 时,cc_library 会从 --fat_apk_cpu 中的列表中传递一个 --cpu 标志。我们可以定义读取这些标志的 config_setting 规则,并在 cc_library 中使用 select 语句,以便您的 cc_library 包含不同的 .so 文件,具体取决于它所使用的架构专为

例如:

# BUILD
CPUS = ["armeabi", "armeabi-v7a", "x86"]
[config_setting(name = cpu, values = {"cpu": cpu}) for cpu in CPUS]

cc_library(
    name = "native_library",
    srcs = select(
        {":%s" % cpu : glob(["libs/%s/*.so" % cpu]) for cpu in CPUS}
    ),
)

android_binary(
    name = "app",
    srcs = glob(["*.java"]),
    manifest = "AndroidManifest.xml",
    deps = [":native_library"],
)

然后在命令行上,您可以指定要在最终 APK 中显示的架构。

$ bazel build --fat_apk_cpu=armeabi,armeabi-v7a,x86 //:app
$ zipinfo -1 bazel-bin/app.apk | grep \.so$
lib/x86/libWatch.so
lib/x86/libSound.so
lib/x86/libSec.so
lib/x86/libTec.so
lib/armeabi-v7a/libWatch.so
lib/armeabi-v7a/libSound.so
lib/armeabi-v7a/libSec.so
lib/armeabi-v7a/libTec.so
lib/armeabi/libWatch.so
lib/armeabi/libSound.so
lib/armeabi/libSec.so
lib/armeabi/libTec.so

$ bazel build --fat_apk_cpu=x86 //:app
$ zipinfo -1 bazel-bin/app.apk | grep \.so$
lib/x86/libWatch.so
lib/x86/libSound.so
lib/x86/libSec.so
lib/x86/libTec.so

仅指定一种架构来构建可以加快您的开发构建。例如,如果您在开发时使用 x86 模拟器,则不需要 armeabi 和 armeabi-v7a .so 文件。