Android NDK学习 <三> Android.mk实例和NDK实用技巧
来源:互联网 发布:淘宝话题 编辑:程序博客网 时间:2024/04/28 18:55
作者:Sam (甄峰)
例1:JNI程序使用libhello-jni.so的符号。
libhello-jni.so由hello-jni.c组成。
hello-jni.c如下:
#include<stdio.h>
#include<android/log.h>
#include<iostream>
#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<stdio.h>
#include<android.h/log.h>
#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.chell-jniB.c
此模块hello-jni由两个C文件组成,因为hello-jni.h只是依赖文件,所以不必加入。注意:LOCAL_SRC_FILES := hello-jni.chell-jniB.c
又因为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<stdio.h>
#include<android/log.h>
#include<iostream>
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 functioniFunctionB1()");
return 0;
}
B2.c
#include "B.h"
int iFunctionB2()
{
LOGI("SamInfo: Enter static functioniFunctionB2()");
return 0;
}
hello-jni.h:
hello-jni.c:hello-jni.h:
#ifndef _HELLO_JNI_H
#define _HELLO_JNI_H
#include<stdio.h>
#include<android/log.h>
#include<iostream>
#include "libstatic/B.h"
#define LOG_TAG "libhello-jni"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#endif
#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/
但请注意:此时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下找到。
而因为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()方式调用。
例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)
例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)
请注意模块名。它将被用作LOCAL_SHARED_LIBRARIES
注1:
NDK实用技巧:
1. 显示NDK Build过程中所有编译选项和动作:
../../ndk-build V=1
2.重新编译:
../../ndk-build -B
或者:
../../ndk-build clean
../../ndk-build
第三方库中编译方法:
Sam常需要NDK编译第三方库,但又不想破坏其原有目录结构.所以通常在src目录中,添加一个目录叫:jni.
在其中添加Android.mk, Application.mk文件。 SourceCode 还是继续使用原有src目录下的源码文件。
在Android.mk中,只需要添加上一级目录的所有.c或者.cpp文件即可。
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/..//*.c)
注意:此处NDK版本为NDK R7C.(不同NDK版本,ndk-build所产生的Makefile并不完全相同)
原文地址:http://blog.sina.com.cn/s/blog_602f877001014kgj.html
0 0
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Android.mk实例和NDK实用技巧
- Android NDK学习之四、 Android.mk实例和NDK实用技巧
- NDK入门:Android.mk实用技巧
- NDK学习笔记:Android.mk
- Android NDK学习之三、 Android.mk的制作
- android ndk Android.mk
- Android NDK --Android.mk
- Android JNI和NDK学习(3)--Android.mk分析
- Android NDK学习 <二> Android.mk
- 【Android】NDK学习之Android.mk
- Android Studio 1.3 到来了,马上来升级
- 提高篇第22-25课作业第一题
- 设计模式之工厂方法模式
- [150529](必看)档案挂靠与打回生源地、暂缓的对比 (广州)
- 动画代码片段
- Android NDK学习 <三> Android.mk实例和NDK实用技巧
- Robot Framework环境搭建
- P124.41
- 第三章 42题
- linux dmesg命令使用
- 邢台治自闭症哪家好
- Spring注解注入
- 货币汇率转换之笔记
- Linux Top 命令解析