首页 > 代码库 > Android.mk语法解析
Android.mk语法解析
Android.mk文件相当于是从Makefile文件中截取的小片段,非常非常的小!可被系统解析一次或者多次!应该尽量少的声明
该文件的一个很重要的组成部分就是模块
1. - a static library 静态库
2. - a shared library 动态库
只需要将动态库安装/拷贝到你的应用程序包即可,静态库是用来生成动态库的
你可以定义一个或多个模块,而且同一source file你可以放到多个模块中
编译之前还有一些细节要注意,比如:不需要将头文件或者一些依赖关系写到Android.mk文件中,NDK会自动给你计算出来的,这就意味这当你的NDK更新了,你也不用担心去修改Android.mk文件了
在详细描述语法之前,来先看一个小例子:
apps/hello-jni/project
在这个工程文件中:
-src文件夹包含了Java源码
-jni文件夹包含了本地源码,比如:jni/hello-jni.c
这个代码实现通过本地调用方法让vm返回去一个字符串生成的共享库
-jni/Android.mk文件,一般内容包含如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
每一个Android.mk文件都必须以LOCAL_PATH变量为开头,call <function> 这个function的内容用的最多的是my-dir,但是还有其他的也可以用,代表的意思你可以去细看,比如all-subdir-makefiles,this-makefile,parent-makefile,grand-parent-makefile,import-module。通过它在development 结构代码中找到你的源文件,在例子当中的宏 函数‘my-dir‘是由编译系统提供的,用来返回当前文件夹的路径,这个路径里包含Android.mk文件
include $(CLEAR_VARS)
这一句也是必须要有的,通过CLEAR_VARS变量来清理除了LOCAL_PATH的整个系统的LOCAL_XXX全局变量的定义,比如OCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, etc...,这样操作完了之后,你就可以在下面进行数据的重新赋值了,担任这个变量也是有编译系统提供的
LOCAL_MODULE := hello-jni
这个是指定你本次要编译生成的动态链接库的文件夹名,必须是独一无二,名字中不能有空格,系统会自动给你添加前缀和后缀的,你现在的名字是hello-jni那么等编译完成之后,生成的文件名是libhello-jni.so
注意:如果你的LOCAL_MODULE := libhello-jni,那么系统将不会给你添加前缀了
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SRC_FILES这个变量必须包含一系列的C/C++源文件来编译和组装到你的模块中,你不需要include你的头文件到这里,因为编译系统会自动计算你的依赖关系,你只需要列出直接编译的需要的文件即可。
默认的C++文件的后缀名是.cpp,如果你想更换的话可以通过LOCAL_CPP_EXTENSION=.c++ 变量来修改,千万不要忘了加‘.‘
还有这个变量下对应的文件或者路径都是相对于你的LOCAL_PATH 来说的,不要写错了
include $(BUILD_SHARED_LIBRARY)
BUILD_SHARED_LIBRARY变量是有编译系统提供的,指向一个GNU的makefile 脚本,用来收集最近一次修改的全局变量的值,确定建立什么,如何精确的执行,使用这个变量,那么你的Android.mk文件必不可少的的要有LOCAL_MODULE和LOCAL_SRC_FILES的定义。生成的库文件规则:lib$(LOCAL_MODULE).so。
编译静态库(BUILD_STATIC_LIBRARY )和上面大同小异,必不可少的的要包含 LOCAL_STATIC_LIBRARIES 和 LOCAL_WHOLE_STATIC_LIBRARIES 的定义。生成库文件的规则是:lib$(LOCAL_MODULE).a
PREBUILT_SHARED_LIBRARY
PREBUILT_STATIC_LIBRARY
预编译共享库和静态库使用方法和都是上面的一样,在Android.mk文件的最后添加一个include $();
不同的地方就是这个Android.mk文件不会生成新的库,而是将你的预编译库拷贝到$PROJECT/obj/local,剥离处理过的拷贝到$PROJECT/libs/<abi>
特别需要注意的地方是,此时你的LOCAL_SRC_FILES 存放的是你的共享库的路径PATH,不在是某个C/C++文件了,同时如果你的共享库还依赖的*.h文件,你还需要通过LOCAL_EXPORT_C_INCLUDES 将文件导过来
TARGET_ARCH
这个设定你的cpu结构是arm x86
TARGET_PLATFORM
网上查看到的值为:generic 这个就是指定你要编译的目标机平台名称,比如:
android-3 -> Official Android 1.5 system images
android-4 -> Official Android 1.6 system images
android-5 -> Official Android 2.0 system images
android-6 -> Official Android 2.0.1 system images
android-7 -> Official Android 2.1 system images
android-8 -> Official Android 2.2 system images
android-9 -> Official Android 2.3 system images
android-14 -> Official Android 4.0 system images
TARGET_ARCH_ABI 这个abi是Application Binary Interface的简称
这个变量的值是有CPU+abi组合而成的
目前支持两种:armeabi 针对的是armv5te指令集 通用性比较强,但是效率要比下面的低
armeabi-v7a 针对的是armv7-a指令集
针对以上两者的区别可以参考:http://www.myexception.cn/android/1594360.html
LOCAL_MODULE_FILENAME
LOCAL_MODULE生成的库文件会自动添加前缀和后缀,但是如果你使用LOCAL_MODULE_FILENAME,那么将会改变之前生成的库文件的名称
注意:该变量的值不能是路径同时名称不能添加后缀名,编译系统会自动为你添加
LOCAL_CPP_EXTENSION
该变量是可选的,当你的C++文件的后缀名不是cpp的时候,你可以使用该变量来指定你的编译系统识别c++后缀的名称
在NDK r7版本之后,该变量可以这么写:LOCAL_CPP_EXTENSION := .cxx .cpp .cc
LOCAL_C_INCLUDES
编译的时候将你要追加的路径添加到此,而且必须放在 LOCAL_CFLAGS / LOCAL_CPPFLAGS 之前,最好是使用LOCAL_C_INCLUDES来代替LOCAL_CFLAGS / LOCAL_CPPFLAGS
LOCAL_LDLIBS
这个是用来加载一些特定的系统库,比如经常用的liblog.so。使用的时候必须添加一个“-l”的前缀
目前遇到的有:
-lz -ldl -lGLESv1_CM -lGLESv2 -ljnigraphics -lOpenSLES -lOpenMAXAL
参考:
http://www.kandroid.org/ndk/docs/ANDROID-MK.html
http://www.cnblogs.com/wainiwann/p/3837936.html