Android NDK学习(二):编译脚本语法Android.mk和Application.mk
一、Android.mk
Android.mk分为一下几部分:
- LOCAL_PATH:= $(call my-dir), 返回当前文件在系统中的路径,Android.mk文件开始时必须定义该变量。
- include $(CLEAR_VARS), 表明清楚上一次构建过程中的所有全局变量,因为在一个Makefile编译脚本中,会使用到大量的全局变量,使用这行脚本表明需要清除所有的全局变量。
- LOCAL_SRC_FILES,要编译的C或者CPP的文件,注意这里不需要列举头文件,构建系统会自动帮助开发者依赖这些文件。
- LOCAL_STATIC_LIBRARIES,所依赖的静态库文件
- LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog -lOPENSLES -lGLESv2 -lEGL -lz,指定编译过程所依赖的NDK提供的动态和静态库,SYSROOT变量代表的是NDK_ROOT下面的目录$NDK_ROOT/platforms/android-18/arch-arm,而在这个目录的usr/lib/目录下有很多对应的so的动态库以及.a的静态库。
- LOCAL_CFLAGS,编译C或者cpp的编译标志,在实际编译的时候会发送给编译器。比如常用的实例是加上-DAUTO_TEST,然后在代码中就可以利用条件判断#ifdef AUTO_TEST来做一些与自动化测试相关的事情。
- LOCAL_LDFLAGS,链接标志的可选列表,当对目标文件进行链接以生成输出文件的时候,将这些标志带给链接器。该指令与LOCAL_LDLIBS有些类似,一般情况下,该选项会用于指定第三方编译的静态库,LOCAL_LDLIBS经常用于指定系统的库(比如log,OpenGL ES, EGL等)。
- LOCAL_MODULE,该模块的编译的目标名,用于区分各个模块,名字必须是唯一并且不包含空格的,如果编译目标是so库,那么该so库的名字就是lib项目名.so。
- include$(BUILD_SHARED_LIBRARY),其实类似的include还有很多,都是构建系统提供的内置变量,该变量的意义就是构建动态库,其他的内置变量还包括如下几种:
--- BUILD_STATIC_LIBRARY:构建静态库
--- PREBUILD_STATIC_LIBRARY:对已有的静态库进行包装,使其成为一个模块。
--- PREBUILD_SHARE_LIBRARY:对已有的动态库进行包装,使其成为一个模块。
--- BUILD_EXECUTABLE:构建可执行文件。
构建系统提供好的这些内置变量在哪里能看大呢?他们都是在$NDK-ROOT/build/core/目录下,这里会有所有预先定义好的Makefile,开发者include一个变量,实际上就是把对应的Makefile包含到Android.mk中,包括前面提到的CLEAR_VARS,其也是该目录下面的一个Makefile。
- include$(call all-makefiles-under, $(LOCAL_PATH)), 也是构建系统提供的变量,该命令会返回该目录下所有子目录的Android.mk列表。
LOCAL_SHARED_LIBRARIES 与 LOCAL_LDLIBS,LOCAL_LDFLAGS的区别?
- LOCAL_LDLIBS :链接的库不产生依赖关系,一般用于不需要重新编译的库,如库不存在,则会报错找不到。且貌似只能链接那些存在于系统目录下本模块需要连接的库。如果某一个库既有动态库又有静态库,那么在默认情况下是链接的动态库而非静态库。如:LOCAL_LDLIBS += -lm –lz –lc -lcutils –lutils –llog …如果你的Android.mk文件中只有这么一行,那么将会采用动态链接。
- LOCAL_SHARED_LIBRARIES 会生成依赖关系,当库不存在时会去编译这个库。
- LOCAL_LDFLAGS:这个编译变量传递给链接器一个一些额外的参数。
注:如果是非系统的第三方库,貌似只能用LOCAL_LDFLAGS方式,LOCAL_LDLIBS方式不行。
二、Application.mk
Application.mk 分为以下几个部分:
- APP_ABI :=xxx , 这里的xxx是指不同的平台,可以选填的有x86、mips、armeabi、armeabi-v7a,all等,值得一提的是若选择all会构建出来所有平台的so,如果不填写此项,默认构建为armeabi平台下的库。
- APP_STL := gnustl_static, NDK构建系统提供了由Android系统给出的最小C++运行时库(/system/lib/libstdc++.so)的C++头文件。然后NDK带有另一个C++实现,开发者可以在自己的应用程序中使用或链接它,定义APP_STL可以选择他们中的一个,包括stlport_static、stlport_shared、gnustl_static.
- APP_CPPFLAGS := -std=gnu++11 -fexceptions,指定编译过程中的flag,可以在该选项中开启 exception rtti 等特性,但为了效率,最好关闭rtti。
- NDK_TOOLCHAIN_VERSION = 4.8,指定交叉工具编译链里面的版本号,这里指定使用4.8。
- APP_PLATFORM:= android-9,指定创建的动态库的平台。
- APP_OPTIM := release, 该变量是可选的,用来定义‘release’或者‘debug’,‘release’模式是默认的,并会生成高度优化的二进制代码,’debug‘模式生成的是未优化的二进制代码,但是可以检测出很多的bug,经常用于调试阶段,也相当于在ndk-build指令后面加上参数 NDK-DEBUG=1。