前言:
Android NDK目前支持预编译库,使用一个编译好的库(动态库/静态库)来使编译过程加快,并且开发人员向外不用提供源码,而是以动态库的形式提供。
1. 使用预编译动态库模块
1.1 申明预编译模块
对于Android编译工具而言,每个预编译库必须声明为一个独立的模块。例如: libc.so 文件与 Android.mk 位于同一个目录中,则可以这样定义该动态库:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libc
LOCAL_SRC_FILES := libc.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/libc
include $(PREBUILT_SHARED_LIBRARY)
注意:LOCAL_EXPORT_C_INCLUDES定义确保了任何依赖这个预编译库的模块
会自动在自己的LOCAL_C_INCLUDES 变量中增加到这个预编译库的include目
录的路径,从而能够找到其中的头文件。
预编译模块不需要编译,因此可以大大减少编译耗时。libc.so预编译模块会被拷贝到 $PROJECT/obj/local 下面,同时还会被拷贝到 $PROJECT/lib/下。
1.2 引用预编译模块
通过第一步申明了预编译模块之后,如果test.c依赖于libc.so。即可以使用LOCAL_SHARED_LIBRARIES列出当前模块的依赖列表。
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES:= test.c
LOCAL_SHARED_LIBRARIES := libc
include $(BUILD_EXECUTABLE)
2. 构建动态库模块
include $(CLEAR_VARS)#这一步操作主要是清空之前定义的LOCAL_XXX开头的变量,是必须要的操作
LOCAL_C_INCLUDES:=$(LOCAL_PATH)/include #定义源文件所需的头文件所需的目录
LOCAL_MODULE:=libhello-android #定义编译出来的模块名
LOCAL_SHARED_LIBRARIES := liblog #编译此模块需要依赖的动态库
LOCAL_SRC_FILES := src/hello-android.c #定义编译模块所需的源文件
include $(BUILD_SHARED_LIBRARY)
3. 其他参数介绍
LOCAL_PATH | 每个Android.mk 文件必须由LOCAL_PATH 开始,用于在development tree 中查找源文件 |
include $(CLEAR_VARS) | CLEAR_VARS指向一个指定的GNU Makefile,并清理许多LOCAL_XXX变量,比如LOCAL_MODULE, LOCAL_SRC_FILES等,它并不清理LOCAL_PATH。因为所有的编译控制文件由同一个GNU Makefile解析和执行,其变量是全局的,所以必须清理后才能避免相互影响 |
LOCAL_MODULE | 每一个模块的名称必须是唯一的且不能包含任何空格。系统在构建
|
LOCAL_SRC_FILES | 指明当前模块的源文件(C/C++文件),缺省的C++源码的扩展名为.cpp . 也可以修改,通过LOCAL_CPP_EXTENSION 修改 |
BUILD_SAHRED_LIBRARY | 该变量指向一个构建脚本并收集所有通过LOCAL_XXX变量指定的关于当前模块的信息,并根据你所列出的源文件构建一个动态库(.so)使用该变量前,你应该至少定义了LOCAL_MODULE和LOCAL_SRC_FILES |
BUILD_STATIC_LIBRARY | 用来构建一个静态库(.a) |
PREBUILT_SHARED_LIBRARY | 用来指定一个预先已经编译好的动态库,与BUILD_SAHRED_LIBRARY 和BUILD_STATIC_LIBRARY 不同,该模块对应的LOCAL_SRC_FILES 不能是源文件,而只能是一个已经编译好的的动态库的路径,如foo/libfoo.so |
PREBUILT_STATIC_LIBRARY | 用来指定一个预先已经编译好的静态库 |
TARGET_ARCH | 指定目标CPU 架构,对于大多数兼容ARM 指令的构建,通常使用arm ,与CPU 架构版本无关 |
TARGET_PLATFORM | 指定目标平台的 例如,androi4.4系统对应的值是:TARGET_PLATFORM := android-19 |
TARGET_ARCH_ABI | 指定
|
TARGET_ABI | 连接了Android API 和ABI 两个值,例如:TARGET_ABI := android-19-arm64-v8a |
LOCAL_MODULE_FILENAME | 该选项可以重写模块的默认名称,例如: LOCAL_MODULE := foo 系统最终会生成 |
LOCAL_SRC_FILES | 包含了构建该模块的源文件列表。可以使用相对路径也可以使用绝对路径,不过最好不要使用绝对路径而使用相对路径,这样可以方便移植 |
LOCAL_CPP_EXTENSION | 指出C++源文件的扩展名 |
LOCAL_CPP_FEATURES | 该变量指明当前模块所依赖的 LOCAL_CPP_FEATURES := rtti --> (use Runtime Type Information) LOCAL_CPP_FEATURES := exceptions --> (use C++ exceptions) |
LOCAL_C_INCLUDES | 指明编译时的include路径列表,相对于NDK ROOT目录 |
LOCAL_CFLAGS | 指明在编译 注意:不要在这改变优化选项和调试等级,这些选项应该在 也可以指定 LOCAL_CFLAGS += -I<path> 这个方法比 |
LOCAL_CXXFLAGS | LOCAL_CPPFLAGS 的别名 |
LOCAL_CPPFLAGS | 指明编译C++代码时的flags,这些选项在编译器的命令行中会跟在LOCAL_CFLAGS后面 |
LOCAL_STATIC_LIBRARIES | 指明编译模块时需要的静态库列表 如果当前模块是动态库或可执行文件,该变量会告诉编译器将该变量列出的静态库连接到最终的二进制文件上 如果当前模块一个静态库,该变量只是简单的指明其他依赖当前模块的库同时也依赖该变量声明的这些库 |
LOCAL_SHARED_LIBRARIES | 列出当前模块在runtime 时依赖的动态库 |
LOCAL_WHOLE_STATIC_LIBRARIES | 静态库全链接,不同于LOCAL_STATIC_LIBRARIES,类似于使用--whole-archive |
LOCAL_LDLIBS | 该变量包含了在编译动态库或可执行文件时的附加连接选项列表。它允许你使用 LOCAL_LDLIBS := -lz 上面的代码告诉编译器在编译模块时还要连接 |
LOCAL_ALLOW_UNDEFIEND_SYMBOLS | 默认情况下,系统在编译动态库时遇到 如果你在编译静态库时指定该变量,系统会忽略该变量 |
LOCAL_ARM_MODE | 默认情况下,系统产生的二进制文件是 也可以将某一个源文件以 注意:也可以在 |
LOCAL_ARM_NEON | 该变量只有在将 上面的代码指明了 |
LOCAL_DISABLE_NO_EXECUTE | Android NDK r4 添加了NX bit 安全特性,该选项默认是开启的,如果要关闭,可以将LOCAL_DISABLE_NO_EXECUTE 这个变量设为true 该变量并不改变 ABI ,同时只在ARMv6+ CPU 的设备开启 |
LOCAL_DISABLE_RELRO | 默认情况下, 这些保护只在 将这个变量 |
LOCAL_DISABLE_FORMAT_STRING_CHECKS | 默认情况下, 系统在编译时会进行string格式的检查。这个检查默认是开启的,不过可以将LOCAL_DISABLE_FORMAT_STRING_CHECKS这个变量设为true来取消这个检查 |
LOCAL_EXPORT_CFLAGS | 在该变量中声明的所有 include $(CLEAR_VARS) include $(CLEAR_VARS) 这里,系统会将 |
LOCAL_EXPORT_CPPFLAGS | 导出include paths ,例如,该变量会告诉bar.c 应该包含foo 模块的头文件 |
LOCAL_EXPORT_LDFLAGS | 该变量作用同LOCAL_EXPORT_CFLAGS ,只不过是针对linker flags |
LOCAL_EXPORT_LDLIBS | 该变量告诉系统传递指定的的系统库给编译器,系统会添加导入的的连接属性给 include $(CLEAR_VARS) include $(CLEAR_VARS) 系统会在编译 |
LOCAL_SHORT_COMMANDS | 当你的模块中有大量源文件或依赖库时,可以将此变量设为true ,之后系统会使用@ 语法来直接包含对象文件或二进制文件,这个特性在Windows 会有用,也可以在Application.mk 中定义APP_SHORT_COMMANDS 来为每个模块开启这一属性 |
LOCAL_THIN_ARCHIVE | 构建静态库时,可以将此变量设为true,系统会产生一个'瘦身了的archive文件,在该库文件中并不包含对象文件,而只是包含每个对象文件对应的路径 |
my-dir | 这个宏返回最后一个 LOCAL_PATH := $(call my-dir) |
all-subdir-makefiles | 返回当前my-dir 路径下所有子目录的所有Android.mk |
this-makefile | 返回当前makefile 的路径 |
parent-makefile | 返回包含当前makefile 的父makefile 的路径 |
grand-parent-makefile | 返回包含当前makefile 的祖父makefile 的路径 |
import-module | 可以用来包含一个指定模块的 |