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

时间:2014-11-01 15:29:05

标签: android-ndk linker static-libraries

我正在为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

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

  • libexif.so(symlink)
  • 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)

这个编译正确,但是当我在调试模式下在手机上运行时,我收到此错误:

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

然后我尝试了这个修改过的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)

没有更多的运气。

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

非常感谢

1 个答案:

答案 0 :(得分:3)

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

> adb pull /system/lib/libexif.so /somepath

然后插入

LOCAL_LDLIBS += /somepath/libexif.so

进入 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? 中提出了直截了当的解决方案:在Makefile中的某个地方摆脱-Wl,--soname=...。不幸的是,这个技巧不适用于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

请注意,您还需要以正确的顺序从Java显式加载依赖库。即静态构造函数看起来像:

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

必须指定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

现在您的Java代码可能更清晰:

    System.loadLibrary("exif.12.3.3");
    System.loadLibrary("exif-native");

以下是 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)

实际上 ,我从不敢尝试的一个技巧可能是将文件libexif.so.12手动打包到assets文件夹中,然后将其解压缩在安装APK之后到某个已知路径,然后使用

    System.load("/known/path/libexif.so.12");
    System.loadLibrary("exif-native");

很遗憾,Android pack / install框架会对libs/armeabi文件夹中的文件进行过滤,只允许使用模式lib<whatever>.so