只要涉及JNI开发都涉及到Android.mk编写,它也是一种makefile语言.
以上一篇博客中提供的工程为例!
<1> : 打印信息 : 既然是一种简易语言那么首先应该知道能够打印脚本信息的语法部分:一个是基本信息类型,一个是警告,错误类型
$(info TEXT......) 这个函数执行的时候,会输出: TEXT... ...
$(error TEXT......)
这个函数被执行的时候,会输出:TEXT......,并且终止make的执行.
$(warning TEXT......)
这个函数被执行的时候,会输出:TEXT......,但是make会继续执行下去.
只要在Android.mk中添加上面的部分,就可以打印Android.mk文件中基本信息.
例如:
LOCAL_PATH := $(call my-dir)
$(warning $(LOCAL_PATH))
build so库时,控制台打印出:
jni/Android.mk:2: jni
<2> : Android.mk的树形组织结构从顶到底链接 : 如果大部分c库都在jni/libmp3lame/目录下,那么一般在libmp3lame子目录下也最好写一个Android.mk的文件,其实android的jni是遵循了linux的文件树管理方式,比如我在上面的libmp3lame目录下新建一个Android.mk文件:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lamejni
LOCAL_SRC_FILES := bitstream.c \
encoder.c \
fft.c \
gain_analysis.c \
id3tag.c \
lame.c \
mpglib_interface.c \
newmdct.c
LOCAL_SRC_FILES += presets.c \
psymodel.c \
quantize_pvt.c \
quantize.c \
reservoir.c \
set_get.c \
tables.c \
util.c
LOCAL_SRC_FILES += takehiro.c \
vbrquantize.c \
VbrTag.c \
version.c
LOCAL_SRC_FILES += xmm_quantize_sub.c
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
然后在jni根目录Android.mk修改为:
LOCAL_PATH := $(call my-dir)
$(warning $(LOCAL_PATH))
DURIAN_MAKEFILE_DIR := ./libmp3lame
LOCAL_SRC_FILES := durianlame.c durianutils.c
include $(LOCAL_PATH)/./$(DURIAN_MAKEFILE_DIR)/Android.mk
其中通过编译器的include 将所需要的mk文件包含进来即可,其中LOCAL_PATH获取的,其他的后面是路径 :
include $(LOCAL_PATH)/./$(DURIAN_MAKEFILE_DIR)/Android.mk
添加一条打印记录:
$(warning $(DURIAN_MAKEFILE_DIR)/Android.mk)
输出:
jni/Android.mk:8: ./libmp3lame/Android.mk
下面给一个通用的写法:通过给出的子目录路径,搜寻所有子目录下的Android.mk文件:
include $(foreach m,$(DURIAN_MAKEFILE_DIR),$(LOCAL_PATH)/./$m/Android.mk)
#include $(LOCAL_PATH)/./$(DURIAN_MAKEFILE_DIR)/Android.mk
注释掉前面的方法.
当然也有另外一种solo全部树下面的写法,个人不推荐:
include $(call all-subdir-makefiles)
<3> : 所有相关的c或者cpp文件 : 同样通过遍历指定子目录下的方式进行:还是紧接着上面的Android.mk内容进行修改:
DURIAN_C_SRCS_DIR :=$(LOCAL_PATH)
DURIAN_ALL_C_SRCS := $(foreach m,$(DURIAN_C_SRCS_DIR),$(wildcard $m/*.c))
$(info $(DURIAN_ALL_C_SRCS))
LOCAL_SRC_FILES := $(DURIAN_ALL_C_SRCS) #durianlame.c durianutils.c
上面是在LOCAL_PATH目录,这个目录在根目录中就是jni跟目录,不过可能很多子目录下Android.mk也有,这个时候LOCAL_PATH的路径就是指向子目录,<1>中也给出的调试信息显示也是jni目录.在这个目录下wildcard后返回这个目录下所有的c文件列表信息,
wildcard用法:
$(wildcard PATTERN...)
它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空.
注意它的返回值,它返回的是一个列表信息.
下面将其改到libmp3lame下的Android.mk文件:
LOCAL_PATH := $(call my-dir)
$(info $(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_MODULE := lamejni
LOCAL_SRC_FILES := bitstream.c \
encoder.c \
fft.c \
gain_analysis.c \
id3tag.c \
lame.c \
mpglib_interface.c \
newmdct.c
LOCAL_SRC_FILES += presets.c \
psymodel.c \
quantize_pvt.c \
quantize.c \
reservoir.c \
set_get.c \
tables.c \
util.c
LOCAL_SRC_FILES += takehiro.c \
vbrquantize.c \
VbrTag.c \
version.c
LOCAL_SRC_FILES += xmm_quantize_sub.c
$(info $(LOCAL_SRC_FILES))
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
C文件很多,添加的时候肯定非常麻烦.
可以更改如下:
DURIAN_C_SRCS_DIR :=$(LOCAL_PATH)
DURIAN_ALL_C_SRCS := $(foreach m,$(DURIAN_C_SRCS_DIR),$(wildcard $m/*.c))
DURIAN_ALL_C_SRCS := $(subst $(LOCAL_PATH)/,,$(DURIAN_ALL_C_SRCS))
LOCAL_SRC_FILES := $(DURIAN_ALL_C_SRCS)
请注意:
DURIAN_ALL_C_SRCS := $(subst $(LOCAL_PATH)/,,$(DURIAN_ALL_C_SRCS))
subst是将前面的DURIAN_ALL_C_SRCS获取的列表的子目录libmp3lame名字全部去掉,读者可以注释掉这一行,看看打印的LOG信息就知道了.当然在jni根目录下也可以使用,更加通用.
有时候要用到其他的so,如果人家只是提供so和so对应的头文件,那么so放到libs下面,头文件通过放到一个单独的目录,同样通过上面的方式导入头文件.
<4> : LOCAL_CFLAGS 用法:这个标记完全是针对编译器的,宏定义的变相写法.
在某些时候,编译源码需要定义宏变量,这个时候,我们可以直接在对应的源码里面去修改,但也有一些情况,我们是没法在别人的源码里定义宏变量的,这个时候,就需要使用到LOCAL_CFLAGS 了 ,举例如下:
Java代码
LOCAL_CFLAGS += -D__FAVOR_BSD
这行代码的作用就是在原有的cflags基础上,再定义一个宏变量__FAVOR_BSD
类似于#define __FAVOR_BSD
LOCAL_CFLAGS: 可选的编译器选项,在编译 C 代码文件的时候使用。这可能是有
用的,指定一个附加的包含路径(相对于NDK的顶层目录),宏定义,或者编译选项。
注意:不要在 Android.mk 中改变 optimization/debugging 级别,只要在 Application.mk 中指定合适的信息,就会自动地为你处理这个问题,在调试期间,会让 NDK自动生成有用的数据文件
还是在举一个有实际意义的例子吧:
在Android.mk文件添加:
LOCAL_CFLAGS += -DDURIAN_DEFINE //定义了该宏,可以在代码中判断
相当于定义了DURIAN_DEFINE的一个宏.
下面具体用法:在你的程序里面通过下面的判断是否调用函数getdurianinformation.
#ifdef DURIAN_DEFINE
getdurianinformation();
#endif
由于上面的是网上问得最多的,所以特别提出来,其余的参考我的cnblog博客上的:
http://www.cnblogs.com/MMLoveMeMM/articles/3909809.html
<5> : 书写Android.mk可能需要很多,但是实际常用的函数,可以归结如下:
1、wildcard : 扩展通配符
2、notdir : 去除路径
3、patsubst :替换通配符
还有一个字符相减的函数subst
当然不同公司和工程可能还有更多.