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 并根据本网站上的一些建议删除了两个符号链接。然后我想用我的应用程序构建它并使用以下 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 文件以及如何传递它?我尝试了一些幼稚的调整,但无法找到如何进行这项工作。
非常感谢
该库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.12到assets文件夹,它解压缩到一些已知的路径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。