android.mk使用简介(以PREBUILT_SHARED_LIBRARY和BUILD_SHARED_LIBRARY扩展描述)

前言:
       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. 其他参数介绍

Android.mk部分参数介绍
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

每一个模块的名称必须是唯一的且不能包含任何空格。系统在构建shared-library时,会自动加上前缀lib和后缀.so

注意:如果模块名称本身已经是以lib开头,则系统不会再加入前缀,只是会加入后缀

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_LIBRARYBUILD_STATIC_LIBRARY不同,该模块对应的LOCAL_SRC_FILES不能是源文件,而只能是一个已经编译好的的动态库的路径,如foo/libfoo.so
PREBUILT_STATIC_LIBRARY用来指定一个预先已经编译好的静态库
TARGET_ARCH指定目标CPU架构,对于大多数兼容ARM指令的构建,通常使用arm,与CPU架构版本无关
TARGET_PLATFORM

指定目标平台的Android API版本号。

例如,androi4.4系统对应的值是:TARGET_PLATFORM := android-19

TARGET_ARCH_ABI

指定CPU的名称和架构,你可以指定一个或多个值,可取的值有:

  • ARMv5TE -----> armeabi
  • ARMv7 -----> armeabi-v7a
  • ARMv8 AArch64 -----> arm64-v8a
  • i686 -----> x86
  • x86-64 -----> x86-64
  • mips32(r1) -----> mips
  • mips64(r6) -----> mips64
  • All -----> all
TARGET_ABI连接了Android APIABI两个值,例如:TARGET_ABI := android-19-arm64-v8a
LOCAL_MODULE_FILENAME

该选项可以重写模块的默认名称,例如:

LOCAL_MODULE := foo
LOCAL_MODULE_FILENAME := libnewfoo

系统最终会生成libnewfoo.so

LOCAL_SRC_FILES包含了构建该模块的源文件列表。可以使用相对路径也可以使用绝对路径,不过最好不要使用绝对路径而使用相对路径,这样可以方便移植
LOCAL_CPP_EXTENSION指出C++源文件的扩展名
LOCAL_CPP_FEATURES

该变量指明当前模块所依赖的C++特性(可选)
推荐使用该变量代替在LOCAL_CPPFLAGS选项中传入-frtti-fexception
使用该变量允许系统对于每个模块各自使用合适的flag,而使用LOCAL_CPPFLAGS则会导致编译器给所有模块都使用传入的flags

LOCAL_CPP_FEATURES := rtti --> (use Runtime Type Information)

LOCAL_CPP_FEATURES := exceptions --> (use C++ exceptions)

LOCAL_C_INCLUDES指明编译时的include路径列表,相对于NDK ROOT目录
LOCAL_CFLAGS

指明在编译C/C++时要添加的flags

注意:不要在这改变优化选项和调试等级,这些选项应该在Application.mk中自动指定

也可以指定include目录:

LOCAL_CFLAGS += -I<path>

这个方法比LOCAL_C_INCLUDES要好一些,因为可以被ndk-gdb所使用

LOCAL_CXXFLAGSLOCAL_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

该变量包含了在编译动态库或可执行文件时的附加连接选项列表。它允许你使用-l前缀来传递指定的系统库,例如:

LOCAL_LDLIBS := -lz

上面的代码告诉编译器在编译模块时还要连接/system/lib/libz.so

LOCAL_ALLOW_UNDEFIEND_SYMBOLS

默认情况下,系统在编译动态库时遇到undefined reference错误时,会抛出undefined symbol error
如果将该变量设为true,则会关闭undefined reference检查

如果你在编译静态库时指定该变量,系统会忽略该变量

LOCAL_ARM_MODE

默认情况下,系统产生的二进制文件是thumb模式,每个指令是16位,并且连接这/thumbSTL libraries。通过将该变量设为arm,可以让产生的指令变为32位,例如:

LOCAL_ARM_MODE := arm

也可以将某一个源文件以.arm结尾以此来指定该文件要被编译成arm模式,例如: 

LOCAL_SRC_FILES := foo.c bar.c.arm

注意:也可以在Application.mk中指定APP_OPTIM := debug来达到同样的目的 

LOCAL_ARM_NEON

该变量只有在将ABI指定为armeabi-v7a时才有效。设置为true时,会讲浮点编译成neon指令,这会极大地加快浮点运算(前提是硬件支持)
同时,也可以将某一个源文件以.neon结尾来指定该源文件支持neon,例如:

LOCAL_SRC_FILES := foo.c.neon bar.c zoo.c.arm.neon

上面的代码指明了zoo.c设为arm模式同时支持neon 

LOCAL_DISABLE_NO_EXECUTEAndroid NDK r4添加了NX bit安全特性,该选项默认是开启的,如果要关闭,可以将LOCAL_DISABLE_NO_EXECUTE这个变量设为true
该变量并不改变ABI,同时只在ARMv6+ CPU的设备开启
LOCAL_DISABLE_RELRO

默认情况下, NDK在编译代码时会加入read-only relocationsGOT protection
该变量指明runtime linkerrelocation之后确保内存为read-only,同时确保security exploit更为困难。

这些保护只在Android API 16及以上才起作用

将这个变量LOCAL_DISABLE_RELRO设为true,可以将上述机制关闭

LOCAL_DISABLE_FORMAT_STRING_CHECKS默认情况下, 系统在编译时会进行string格式的检查。这个检查默认是开启的,不过可以将LOCAL_DISABLE_FORMAT_STRING_CHECKS这个变量设为true来取消这个检查
 
LOCAL_EXPORT_CFLAGS

在该变量中声明的所有flags都会添加到在那些以LOCAL_STATIC_LIBRARIES或者LOCAL_SHARED_LIBRARIES声明依赖当前静态库或动态库的模块的LOCAL_CFLAGS中,例如:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLGAS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SAHRED_LIBRARY)

这里,系统会将-DFOO=1-DBAR=2都传入给bar.c
另外,所有依赖关系都是传递的,如果zoo依赖bar,而bar又依赖foo,则zoo同样继承了foo模块的所有exported flags
系统并不会传递exported flags给当前模块,举例来说,-DFOO=1并不会传递给foo

LOCAL_EXPORT_CPPFLAGS导出include paths,例如,该变量会告诉bar.c应该包含foo模块的头文件
LOCAL_EXPORT_LDFLAGS该变量作用同LOCAL_EXPORT_CFLAGS,只不过是针对linker flags
LOCAL_EXPORT_LDLIBS

该变量告诉系统传递指定的的系统库给编译器,系统会添加导入的的连接属性给LOCAL_LDLIBS,例如:

include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)

系统会在编译libbar.so时将-llog放在连接命令行末端

LOCAL_SHORT_COMMANDS当你的模块中有大量源文件或依赖库时,可以将此变量设为true,之后系统会使用@语法来直接包含对象文件或二进制文件,这个特性在Windows会有用,也可以在Application.mk中定义APP_SHORT_COMMANDS来为每个模块开启这一属性
LOCAL_THIN_ARCHIVE构建静态库时,可以将此变量设为true,系统会产生一个'瘦身了的archive文件,在该库文件中并不包含对象文件,而只是包含每个对象文件对应的路径
my-dir

这个宏返回最后一个makefile的路径,一般都是当前Android.mk的路径,这个宏一般用来在Android.mk开头定义LOCAL_PATH变量,例如:

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

可以用来包含一个指定模块的Android.mk,用法是:

$(call import-module,<name>)


 

      
 

原文

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值