Android NDK编译中在libs\armeabi中加入第三方so库文件的方法
Android NDK編譯中在libs\armeabi中加入第三方so庫文件的方法
假設要加入庫文件的名字為libffmpeg.so文件
1.要在project\jni目錄下新建一目錄prebuilt,把libffmpeg.so文件copy到project\jni\prebuilt中,并在目錄project\jni\prebuilt中添加文件Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)
2.在project\jni目錄下的Android.mk文件中加入
LOCAL_SHARED_LIBRARIES := ffmpeg
并在末尾加入
include $(LOCAL_PATH)/prebuilt/Android.mk
一般模板的寫法如下:
Android NDK about Library (static library , share library and 3rd party library)
A:Static library
文件Android.mk:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jniLOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_STATIC_LIBRARY)
文件Application.mk:
APP_MODULES?:=hello-jni
B:?Share library
文件Android.mk:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jniLOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_SHARED_LIBRARY)
C:?Static library+Share library
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_MODULE := mylib_staticLOCAL_SRC_FILES := src.cinclude $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)LOCAL_MODULE := mylib_sharedLOCAL_SRC_FILES := src2.c
LOCAL_STATIC_LIBRARIES?:= mylib_static
include $(BUILD_SHARED_LIBRARY)
D:Using 3rd party library
文件Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)LOCAL_MODULE := thirdlib1 # name it whateverLOCAL_SRC_FILES :=?$(TARGET_ARCH_ABI)/libthird1.a?# or $(so_path)/libthird1.so#LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/includeinclude $(PREBUILT_STATIC_LIBRARY) #or?PREBUILT_SHARED_LIBRARY
include $(CLEAR_VARS)LOCAL_MODULE := mylib_use_thirdlibLOCAL_SRC_FILES := src.c
LOCAL_STATIC_LIBRARIES?:= thirdlib1 #or?LOCAL_SHARED_LIBRARY
include $(BUILD_SHARED_LIBRARY)?#if static lib,need Application.mk(needn't,I have cheked!)
When I use the static library ,I always got the?undefined reference to**?error no matter what I do.After a whole tough day,I found that?it's not the problem of the mk file,it's the library!Holy Shit!!
My static library was built in cygwin of windows.Of course it can't be used in Linux!!!!Then I built it with android ndk tool and it runs perfectly!!!
a. check your library's mode (whether it isARM)
$ file libtest.solibtest.so: ELF 32-bit LSB shared object,?ARM, version 1 (SYSV), dynamically linked, not stripped
make sure you library is ARM mode.
b. use?nm?to view the method of the so file
$ nm libtutorial.so |grep T00001344 a _GLOBAL_OFFSET_TABLE_000002a8 T getinformation000002b4 T getinformation2
To use android ndk tool:http://stackoverflow.com/questions/7403036/compile-library-for-android-ndk
?
//@Android.mk??//靜態庫的編寫
?
LOCAL_PATH:= $(call my-dir)
?
include $(CLEAR_VARS)
?
LOCAL_PRELINK_MODULE := false
LOCAL_ARM_MODE := arm
?
LOCAL_SRC_FILES:= /
?
???aa.c bb.c dd.c /
?
LOCAL_SHARED_LIBRARIES := /
?
??dd ee ff /
?
LOCAL_C_INCLUDES += /
????????$(LOCAL_PATH)/../inc
?
LOCAL_CFLAGS += -MD /
?
-FF -Uarm -DMODULE -D__LINUX_ARM_ARCH__=7 /
?
LOCAL_MODULE:= libMyStaticLib
?
include $(BUILD_STATIC_LIBRARY)
?
//靜態庫生成后的文件是libMyStaticLib.a
?
//@Android.mk??//動態庫的編寫
?
LOCAL_PATH:= $(call my-dir)
?
include $(CLEAR_VARS)
?
LOCAL_PRELINK_MODULE := false
LOCAL_ARM_MODE := arm
?
LOCAL_SRC_FILES:= /
?
???aa.c bb.c dd.c /
?
LOCAL_SHARED_LIBRARIES := /
?
??dd ee ff /
?
LOCAL_C_INCLUDES += /
????????$(LOCAL_PATH)/../inc
?
LOCAL_CFLAGS += -MD /
?
-FF -Uarm -DMODULE -D__LINUX_ARM_ARCH__=7 /
?
LOCAL_MODULE:= libMyShareLib
?
include $(BUILD_SHARED_LIBRARY)
?
//動態庫生成后的文件是libMyShareLib.so
?
?
實例教程如下:
例1:JNI程序使用libhello-jni.so的符號。
libhello-jni.so由hello-jni.c組成。
?
hello-jni.c如下:
?
#include
#include
#include
?
?
?
#define??LOG_TAG????"libhello-jni"
#define??LOGE(...)??__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
?
void Java_com_example_hellojni_HelloJni_functionA(JNIEnv* env, jobject thiz)
{
LOGE("SamInfo: Enter Native functionA");
return;
}
?
Android.mk如下:
LOCAL_PATH := $(call my-dir)
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDLIBS := -llog
?
include $(BUILD_SHARED_LIBRARY)
?
../../../ndk-build -B V=1
?
可以正常編譯,再使用Eclipse編譯Android工程,可正常運行。
?
例2:JNI程序使用libhello-jni.so的符號。
libhello-jni.so由hello-jni.c,hell-jniB.c,頭文件hello-jni.h組成。
?
hello-jni.h如下:
#ifndef _HELLO_JNI_H
#define _HELLO_JNI_H
?
#include
#include
#include
?
#define??LOG_TAG????"libhello-jni"
#define??LOGE(...)??__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
?
#endif
?
hello-jni.c如下:
#include "hello-jni.h"
?
void Java_com_example_hellojni_HelloJni_functionA(JNIEnv* env, jobject thiz)
{
LOGE("SamInfo: Enter Native functionA");
return;
}
?
hell-jniB.c如下:
#include "hello-jni.h"
?
?
void Java_com_example_hellojni_HelloJni_functionB(JNIEnv* env, jobject thiz)
{
LOGE("SamInfo: Enter Native functionB");
return;
}
?
Android.mk如下:
LOCAL_PATH := $(call my-dir)
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
?
LOCAL_LDLIBS := -llog
?
?
include $(BUILD_SHARED_LIBRARY)
?
注意:LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
此模塊hello-jni由兩個C文件組成,因為hello-jni.h只是依賴文件,所以不必加入。
又因為hello-jni.h在project/jni目錄中,此目錄本身為-I,所以也不用再Android.h中指出。
?
?
?
例3:JNI程序使用libhello-jni.so的符號。
libhello-jni.so依賴于libB.a.
libhello-jni.so由hello-jni.c,hell-jniB.c,頭文件hello-jni.h組成。
libB.a由libstatic/B1.c,libstatic/B2.c頭文件libstatic/B.h組成。
?
B.h?如下:
#ifndef _B_H
#define _B_H
?
#include
#include
#include
?
int iFunctionB1();
int iFunctionB2();
?
#define??LOG_TAG????"libStatic"
#define??LOGI(...)??__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
?
#endif
?
B1.c:
#include "B.h"
?
?
int iFunctionB1()
{
LOGI("SamInfo: Enter static function iFunctionB1()");
return 0;
}
?
B2.c
#include "B.h"
?
?
int iFunctionB2()
{
LOGI("SamInfo: Enter static function iFunctionB2()");
return 0;
}
?
?
?
hello-jni.h:
#ifndef _HELLO_JNI_H
#define _HELLO_JNI_H
?
#include
#include
#include
?
#include "libstatic/B.h"
?
#define??LOG_TAG????"libhello-jni"
#define??LOGE(...)??__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
?
?
#endif
?
?
hello-jni.c:
?
#include "hello-jni.h"
?
void Java_com_example_hellojni_HelloJni_functionA(JNIEnv* env, jobject thiz)
{
LOGE("SamInfo: Enter Native functionA");
iFunctionB1();
return;
}
?
?
hell-jniB.c:
#include "hello-jni.h"
?
?
void Java_com_example_hellojni_HelloJni_functionB(JNIEnv* env, jobject thiz)
{
LOGE("SamInfo: Enter Native functionB");
iFunctionB2();
return;
}
?
?
?
Android.mk如下:
LOCAL_PATH := $(call my-dir)
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-B
LOCAL_SRC_FILES := libstatic/B1.c libstatic/B2.c
?
include $(BUILD_STATIC_LIBRARY)
?
?
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
LOCAL_STATIC_LIBRARIES := hello-B
LOCAL_LDLIBS := -llog
?
include $(BUILD_SHARED_LIBRARY)
?
這就是典型的一個Android.mk中包含2個Modules的例子。其中一個是產生靜態庫,另一個產生動態庫。
動態庫依賴于靜態庫。(一定要添加?LOCAL_STATIC_LIBRARIES := hello-B?,否則不生成靜態庫)
?
?
?
例4:JNI程序使用libA.so(由A1.c,A2,c,A.h組成)
libA.so依賴于libB.so(由B1.c,B2.c,B.h組成)
?
情況分析:
因為libB.so被libA.so使用。所以肯定要加入:
LOCAL_LDLIBS := -L$(LOCAL_PATH)/../libs/armeabi/???-lhello-B
?
但請注意:此時libA.so中所用到的libB.so?的符號只是一個空穴。并為將實現加進來。
?
而如果使用:
LOCAL_SHARED_LIBRARIES := hello-B
也僅僅是將libhello-B.so?添加進編譯選項。并未將符號添加進去。
?
在Linux下,此類情況可以將動態庫放置于某個目錄下,然后使用export LD_LIBRARY_PATH?來解決。但Android下并無此方法。導致運行時會找不到libhello-B.so中的符號。
?
?
針對此類情況,有兩種方法,但都不是特別好用。分別描述如下:
?
方法1.
將libhello-B.so放置于/system/lib下。
且Android.mk如下:
LOCAL_PATH := $(call my-dir)
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-B
LOCAL_SRC_FILES := libstatic/B1.c libstatic/B2.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
?
?
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
#LOCAL_SHARED_LIBRARIES := hello-B
LOCAL_LDLIBS := -llog??-L$(LOCAL_PATH)/../libs/armeabi/???-lhello-B
?
include $(BUILD_SHARED_LIBRARY)
?
此Android.mk有兩個模塊,分別產生libhello-B.so, libhello-jni.so.?后者依賴于前者。
?
而因為Java層程序使用:System.loadLibrary("hello-jni");
則libhello-jni.so的符號加入到Java應用程序中。而它使用到的libhello-B.so,則能夠在/system/lib下找到。
?
?
方法2.?將libhello-B.so也添加如Java程序中。且放置于hello-jni之前。
System.loadLibrary("hello-B");
System.loadLibrary("hello-jni");
?
?
方法3:
可以使用dlopen()方式調用。
?據說使用-rpath可以指定應用程序查找庫的目錄。但Sam覺得理論上并不可能(因為Java無法指定Wl,-rpath).也沒有嘗試出來。
?
?
?
?
例5:JNI程序使用libA.so(由A1.c A2.c, A.h組成)
libA.so依賴于libB.so(由B1.c, B2.c, B.h組成)
libB.so依賴于libC.so(由c.c組成)和libD.a(由d.c組成)
libC.so依賴于libD.a?(由d.c組成)
?
?
Android.mk:
LOCAL_PATH := $(call my-dir)
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-B
LOCAL_SRC_FILES := libstatic/B1.c libstatic/B2.c
LOCAL_STATIC_LIBRARIES := D
LOCAL_LDLIBS := -llog -lC -L$(LOCAL_PATH)/../libs/armeabi/
include $(BUILD_SHARED_LIBRARY)
?
?
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
#LOCAL_SHARED_LIBRARIES := hello-B
LOCAL_LDLIBS := -llog??-L$(LOCAL_PATH)/../libs/armeabi/???-lhello-B
include $(BUILD_SHARED_LIBRARY)
?
?
include $(CLEAR_VARS)
LOCAL_MODULE????:= C
LOCAL_SRC_FILES := c.c
LOCAL_LDLIBS := -llog
LOCAL_STATIC_LIBRARIES := D
include $(BUILD_SHARED_LIBRARY)
?
?
include $(CLEAR_VARS)
LOCAL_MODULE????:= D
LOCAL_SRC_FILES := d.c
LOCAL_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)
?
?
?
請注意:如此寫法:則libD.a中的符號分別被:libC.so, libB.so兩次引用。
?
?
?
例6:?JNI程序使用libA.so(由A1.c A2.c, A.h組成)
并引用外部生成的:libE.so, libF.a.
?
Sam:經常發生這樣的情況,某NDK工程A生成一個動態庫,供另一個NDK工程B使用。我們常把此動態庫放到B工程的lib/armeabi下。?但ndk-build時,它會首先刪除lib/armeabi下所有.so文件。
所以可以使用?PREBUILT_SHARED_LIBRARY
Android.mk:
LOCAL_PATH := $(call my-dir)
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-B
LOCAL_SRC_FILES := libstatic/B1.c libstatic/B2.c
LOCAL_SHARED_LIBRARIES := prelib
?
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
?
?
?
?
include $(CLEAR_VARS)
?
LOCAL_MODULE????:= hello-jni
LOCAL_SRC_FILES := hello-jni.c hell-jniB.c
#LOCAL_SHARED_LIBRARIES := hello-B
LOCAL_LDLIBS := -llog??-L$(LOCAL_PATH)/../libs/armeabi/???-lhello-B
include $(BUILD_SHARED_LIBRARY)
?
include $(CLEAR_VARS)
LOCAL_MODULE := prelib
LOCAL_SRC_FILES := libE.so
?
include $(PREBUILT_SHARED_LIBRARY)
?
?
注意:當?PREBUILT_SHARED_LIBRARY?時,LOCAL_SRC_FILES不再是.c文件,而是動態庫。它可以放置在jni下。編譯時,它會自動被copy到lib/armaebi下。
請注意模塊名。它將被用作LOCAL_SHARED_LIBRARIES
轉載于:https://blog.51cto.com/6151207/1622730
總結
以上是生活随笔為你收集整理的Android NDK编译中在libs\armeabi中加入第三方so库文件的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: phpcms URL修改
- 下一篇: rpm 安装ipython