android共享库中.so.12文件的不满意链接

tis*_*shu 2 linker static-libraries android-ndk

我正在为 Android 构建 libexif。我正在使用以下交叉编译脚本:

PLATFORM_PREFIX=/home/tishu/Documents/osx-wks/GC/Thdl/jni/libexif-0.6.21/arch-arm/
NDK_PATH=/home/tishu/Documents/android-ndk-r8e/
NDK_PLATFORM=android-14

rmdir $PLATFORM_PREFIX
mkdir $PLATFORM_PREFIX

$NDK_PATH/build/tools/make-standalone-toolchain.sh  --system=linux-x86_64 --platform=$NDK_PLATFORM --install-dir=$PLATFORM_PREFIX

PATH=$PLATFORM_PREFIX/bin:$PATH

./configure --host=arm-linux-androideabi --prefix=$PLATFORM_PREFIX --enable-static
make clean
make install
Run Code Online (Sandbox Code Playgroud)

输出在 lib 文件夹中提供了 3 个 .so 文件

  • libexif.so(符号链接)
  • libexif.so.12(看起来像一个符号链接,但内容是大二进制)
  • libexif.so.12.3.3(实际二进制)

我已将最后一个文件重命名为 libexif.so 并根据本网站上的一些建议删除了两个符号链接。然后我想用我的应用程序构建它并使用以下 Android.mk,其中 libexif_native 是我使用 libexif 库的 c 文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libexif
LOCAL_SRC_FILES := libexif-0.6.21/arch-arm/lib/libexif.so
LOCAL_EXPORT_C_INCLUDES := libexif-0.6.21/arch-arm/include
LOCAL_EXPORT_LDLIBS := libexif-0.6.21/arch-arm/lib/libexif.so
LOCAL_PRELINK_MODULE := true
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
LOCAL_MODULE := libexif_native
LOCAL_SRC_FILES := libexif_native1.1.4.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexif-0.6.21/arch-arm/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SHARED_LIBRARY := libexif
LOCAL_LDLIBS    := -llog -ljnigraphics -lz -lm $(LOCAL_PATH)/libexif-0.6.21/arch-arm/lib/libexif.so
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

这可以正确编译,但是当我以调试模式在手机上运行它时,出现此错误:

11-01 15:05:06.919: E/AndroidRuntime(5638): FATAL EXCEPTION: main
11-01 15:05:06.919: E/AndroidRuntime(5638): java.lang.UnsatisfiedLinkError: dlopen failed: could not load library "libexif.so.12" needed by "libexif_native.so"; caused by library "libexif.so.12" not found
Run Code Online (Sandbox Code Playgroud)

然后我尝试了这个修改过的 Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libexif
LOCAL_SRC_FILES := libexif-0.6.21/arch-arm/lib/libexif.so
LOCAL_EXPORT_C_INCLUDES := libexif-0.6.21/arch-arm/include
LOCAL_EXPORT_LDLIBS := libexif-0.6.21/arch-arm/lib/libexif.so
LOCAL_EXPORT_LDLIBS := libexif-0.6.21/arch-arm/lib/libexif.so.12
LOCAL_PRELINK_MODULE := true
include $(PREBUILT_SHARED_LIBRARY)


include $(CLEAR_VARS)
LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
LOCAL_MODULE := libexif_native
LOCAL_SRC_FILES := libexif_native1.1.4.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libexif-0.6.21/arch-arm/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_SHARED_LIBRARY := libexif
LOCAL_LDLIBS    := -llog -ljnigraphics -lz -lm $(LOCAL_PATH)/libexif-0.6.21/arch-arm/lib/libexif.so.12 -lm $(LOCAL_PATH)/libexif-0.6.21/arch-arm/lib/libexif.so.12
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

没有更多的运气。

任何人都知道它为什么要寻找 .12 文件以及如何传递它?我尝试了一些幼稚的调整,但无法找到如何进行这项工作。

非常感谢

Ale*_*ohn 5

该库libexif.so是标准 Android 发行版的一部分。如果您不依赖最新版本的某些特殊功能,您可能会发现这/system/lib/libexif.so对您来说还可以。无需构建库并解决所有问题(见下文),您可以将您libexif-native.so的库与系统库链接:只需从您的设备中拉出库:

> adb pull /system/lib/libexif.so /somepath
Run Code Online (Sandbox Code Playgroud)

然后插入

LOCAL_LDLIBS += /somepath/libexif.so
Run Code Online (Sandbox Code Playgroud)

进入你的Android.mk。请注意,您会看到

Android NDK:警告:jni/Android.mk:...:链接器标志中的非系统库:/somepath/libexif.so

在这种特定情况下,您可以放心地忽略此警告。

你这样避免的麻烦

Linux 库的 Android 移植是一个典型的问题,后者使用 SONAME 的版本后缀,而 Android NDK 不支持这样的后缀。有一个很好的理由:在 Android 上,库不是在系统范围内安装的,它们始终是应用程序包的一部分,因此不需要版本标记。但是这种不一致并没有让 Android 开发者的生活更轻松。

How to modify librtmp Makefile to remove version suffix? 中建议了简单的解决方案: 摆脱-Wl,--soname=...你的 Makefile 中的某个地方。不幸的是,这个技巧不适用于 NDK r9d 或 r10c。

但是您可以LDFLAGS./configure. 这是命令:

./configure LDFLAGS=-Wl,soname=libexif.so <other parameters>
make
mv /arch-arm/lib/libexif.so.12.3.3 /arch-arm/lib/libexif.so
Run Code Online (Sandbox Code Playgroud)

请注意,您还需要以正确的顺序从 Java 显式加载依赖项库。即静态构造函数将如下所示:

static {
    System.load("/data/data/your.package.name/lib/libexif.so");
    System.loadLibrary("exif-native");
}
Run Code Online (Sandbox Code Playgroud)

必须指定到的完整路径,libexif.so否则/system/lib将从中加载库。

或者,您应该重命名库

./configure LDFLAGS=-Wl,soname=libexif.12.3.3.so <other parameters>
make
mv /arch-arm/lib/libexif.so.12.3.3 /arch-arm/lib/libexif.12.3.3.so
Run Code Online (Sandbox Code Playgroud)

现在你的 Java 代码可能更干净了:

    System.loadLibrary("exif.12.3.3");
    System.loadLibrary("exif-native");
Run Code Online (Sandbox Code Playgroud)

这是Android.mk的相关片段:

LOCAL_MODULE := libexif
LOCAL_SRC_FILES := libexif-0.6.21/arch-arm/lib/libexif.12.3.3.so
LOCAL_EXPORT_C_INCLUDES := libexif-0.6.21/arch-arm/include
include $(PREBUILT_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)

其实,一个把戏,我从来不敢尝试可能是手动打包文件libexif.so.12assets文件夹,它解压缩到一些已知的路径APK安装后,与使用

    System.load("/known/path/libexif.so.12");
    System.loadLibrary("exif-native");
Run Code Online (Sandbox Code Playgroud)

遗憾的是,Android 打包/安装框架对文件libs/armeabi夹中的文件进行过滤,只允许 pattern lib<whatever>.so