Android.mk的解析

一、概述

Android.mk作用是将源文件按照module进行分组,然后将module生成静态库、共享库或者可执行文件

一个Android.mk里面可能有1个或者多个module,不同的module之间可以使用相同的源文件。

Android.mk里面不用列出头文件,Build System会帮我们处理

只有动态库可以被install或者copy到应用程序包,静态库可以被链接成动态库

二、语法

举例说明:

LOCAL_PATH := $(call my-dir)

 

include $(CLEAR_VARS)

 

LOCAL_MODULE    := hello-jni

LOCAL_SRC_FILES := hello-jni.c

 

include $(BUILD_SHARED_LIBRARY)

解析如下:

LOCAL_PATH := $(call my-dir)

Android.mk必须以定义LOCAL_PATH开头,表示源文件的位置,my-dir返回的是Android.mk的目录路径

 

include $(CLEAR_VARS)

负责清除所有的LOCAL_XXX变量,例如:LOCAL_MODULE、 LOCAL_SRC_FILES、LOCAL_STATIC_LIBRARIES等,但是不包括LOCAL_PATH,这个清理动作必须要有的,因为这些比阿尼朗都是全局的,防止之前被赋值,导致当前module解析编译异常

 

LOCAL_MODULE := hello-jni

LOCAL_MODULE可以配置模块的名字,模块的名字必须是唯一的并且中间不能包含空格,Build System会自动添加前缀和后缀,例如:模块名字是foo,要生成动态库,那么生成的动态库名字就是libfoo.so,其中前缀是lib,后缀是.so,但是如果名字是libfoo,前缀就不会添加了。生成的动态库的名字依然是libfoo.so

 

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SRC_FILES变量里面包含的是模块用到的C/C++的源码,不必列出头文件,Build System会自动帮我们找到依赖文件,当包含C++源码是,这些文件的后缀默认是.cpp,如果文件后缀不是.cpp,则需要通过LOCAL_CPP_EXTENSION进行修改(后面单独介绍这个变量)。

 

include $(BUILD_SHARED_LIBRARY)

BUILD_SHARED_LIBRARY变量指向一个GNU Makefile脚本,它负责收集自从上次调用 include $(CLEAR_VARS)到这一行之间的所有LOCAL_XXX信息,并编译成动态库。也可以使用别的值,例如:

BUILD_STATIC_LIBRARY:编译为静态库。

BUILD_SHARED_LIBRARY :编译为动态库

BUILD_EXECUTABLE:编译为Native C可执行程序

三、NDK Build System变量:

1、NDK Build System 保留了以下变量名:

(1)以LOCAL_  为开头的

(2)以PRIVATE_ ,NDK_ 或者APP_ 开头的名字

(3)小写字母名字,如my-dir

注意:如果要在Android.mk定义自己使用的变量名,建议使用MY_ 开头

2、NDK 定义的 include 变量

2.1:CLEAR_VARS:这个变量指向一个编译脚本,这个脚本是用来取消几乎所有LOCAL_XXX变量(LOCAL_PATH除外)。所以在描述新模块之前,必须使用此变量

例如:

include $(CLEAR_VARS)

 

2.2:BUILD_SHARED_LIBRARY:指向一个编译脚本,这个脚本会收集自从上次调用 include $(CLEAR_VARS)  到这一行之间所有的LOCAL_XXX信息。并决定如何这中间列出的源文件编译成动态库。

注意:在此行之前前,至少应该包含:LOCAL_MODULE和LOCAL_SRC_FILES

例如:

include $(BUILD_SHARED_LIBRARY)

 

2.3:BUILD_STATIC_LIBRARY:与2.2类似,它也指向一个编译脚本,这个脚本会收集自从上次调用 include $(CLEAR_VARS) 到这一行之间所有的LOCAL_XXX信息。并决定如何这中间列出的源文件编译成静态库。

注意:静态库不能够加入到Project 或者APK中。但它可以用来生成动态库。

例如:

include $(BUILD_STATIC_LIBRARY)

 

2.4: BUILD_EXECUTABLE: 与2.2类似,它也指向一个编译脚本,这个脚本会收集自从上次调用 include $(CLEAR_VARS) 到这一行之间所有的LOCAL_XXX信息。并决定如何这中间列出的源文件编译成Native程序。

例如:

include $(BUILD_EXECUTABLE)

 

2.5:PREBUILT_SHARED_LIBRARY:指向一个编译脚本,这个脚本可以指定一个预编译的共享库,与BUILD_SHARED_LIBRARY和BUILD_STATIC_LIBRARY不同,此时LOCAL_SRC_FILES应该被指定为预编译动态库的路径(例如:/foo/libfoo.so),而不是源文件

例如:

include $(PREBUILT_SHARED_LIBRARY)

例如:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := foo-prebuilt     # 模块名

LOCAL_SRC_FILES := libfoo.so     # 模块的文件路径(相对于 LOCAL_PATH)

include $(PREBUILT_SHARED_LIBRARY)

预编译库的使用请参照https://developer.android.google.cn/ndk/guides/prebuilts

 

2.6: PREBUILT_STATIC_LIBRARY: 预先编译的静态库。

与2.5类似

 

3、平台信息变量

Build system根据APP_ABI变量所指定的每个 ABI 分别解析一次Android.mk,该变量通常在Application.mk文件中定义。如果APP_ABI为all表示Build System会根据NDK支持的每个ABI分别解析一次Android.mk

 

3.1: TARGET_ARCH:

这个参数表示的是CPU架构,可以是arm、arm64、x86或x86_64中的一个

 

3.2: TARGET_PLATFORM:

这个参数表示的是Android API level,例如:Android 5.1的Android API level对应的是android-22

例如:

ifeq ($(TARGET_PLATFORM),android-22)

    # ... do something ...

Endif

 

3.3:TARGET_ARCH_ABI

这个参数表示的是CPU架构及其支持的ABI

例如:

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)

    # ... do something ...

Endif

 

3.4:TARGET_ABI

这个参数表示的是Android API level和ABI

例如:

ifeq ($(TARGET_ABI),android-22-arm64-v8a)

    # ... do something ...

Endif

 

4、模块描述变量

这类变量是用来向Build System描述模块信息,位于include $(CLEAR_VARS)和 include $(BUILD_XXXXX)之间。其中include $(CLEAR_VARS)用来清空这些变量,所以在一个新模块开始的时候,需要先调用include $(CLEAR_VARS)

 

4.1: LOCAL_PATH:

这个变量指定当前文件的路径,必须在Android.mk的开头,另外include $(CLEAR_VARS)不会清理这个变量

例如:

LOCAL_PATH := $(call my-dir)

 

4.2: LOCAL_MODULE:

这个变量用来设置模块名,模块名必须是唯一的,并且模块名内部不能有空格,在include $(BUILD_XXXXX)之前,必须要先定义这个变量。无需添加lib前缀和.so或.a后缀,build system会自动添加,如果名字是lib开头,例如libfoo,则build system不会再添加lib前缀

例如:

LOCAL_MODULE := "foo"

 

4.3: LOCAL_MODULE_FILENAME:

这个变量是可选的,LOCAL_MODULE只能生成libxxx.so或者libxxx.a这种名字,如果要生成其他名字可以使用这个变量替换系统自动生成的名字。

例如:

LOCAL_MODULE := foo

LOCAL_MODULE_FILENAME := libnewfoo

这样生成的名字就是libnewfoo.so而不是libfoo.so

 

4.4:LOCAL_SRC_FILES:

这个变量提供build system用来生成模块的源文件列表。不需要列出依赖文件。文件路径可以是相对路径也可以是绝对路径,绝对路径是相对于LOCAL_PATH的,官方建议使用相对路径提高可以执行

例如:

LOCAL_SRC_FILES := $(call all-java-files-under, src)   

LOCAL_SRC_FILES += \

                src/com/sdk/service/abc.aidl \

                src/com/sdk/service/abcCallback.aidl

 

4.5: LOCAL_CPP_EXTENSION:

这个变量是可选的,用来设置C++源文件的扩展名

例如:

LOCAL_CPP_EXTENSION := .cxx

LOCAL_CPP_EXTENSION := .cxx .cpp .cc

 

4.6:LOCAL_CPP_FEATURES:

这个变量是可选的,用来指定C++ features,C++features启用 -frtti和-fexceptions时,不要使用LOCAL_CPPFLAGS,这个变量会导致编译器将制定的features用于所有模块,所以要使用LOCAL_CPP_FEATURES

例如:

LOCAL_CPP_FEATURES := rtti

LOCAL_CPP_FEATURES := exceptions

也可以这样

LOCAL_CPP_FEATURES := rtti features

 

4.7:LOCAL_C_INCLUDES:

这个变量是可选的,添加编译时,C、C++头文件搜索路径

例如:

LOCAL_C_INCLUDES := sources/foo

LOCAL_C_INCLUDES := $(LOCAL_PATH)/<subdirectory>/foo

Define this variable before setting any corresponding inclusion flags via LOCAL_CFLAGS or LOCAL_CPPFLAGS.

 

4.8: LOCAL_CFLAGS:

这个变量是可选的,可以在编译C/C++源文件时用来附加编译选项。

注意:不要在此处修改编译的优化选项和Debug等级。Build system会使用Application.mk中的信息自动处理。

可以使用LOCAL_CFLAGS指定头文件检测路径

LOCAL_CFLAGS += -I<path>,

这个方法比使用LOCAL_C_INCLUDES要好,这样也可以被ndk-debug使用。

 

4.9: LOCAL_CPPFLAGS:

这个变量是可选的,只能给C++源文件附加编译选项。要在LOCAL_CFLAGS之后

 

4.10: LOCAL_STATIC_LIBRARIES:

这个变量用来列出当前模块需要的静态库的列表

 

4.11: LOCAL_SHARED_LIBRARIES:

这个变量用来列出当前模块需要的动态库的列表

 

4.12:LOCAL_WHOLE_STATIC_LIBRARIES:

具体参考--whole-archive

 

4.13:LOCAL_LDLIBS:

这个变量可以用来添加系统库。 如 -lz:

例如:

LOCAL_LDLIBS := -lz

注意:这个是编译动态库用的,为静态库使用此变量,会被忽略

 

4.14: LOCAL_LDFLAGS

这个变量可以用来指定其他ld,例如要在ARM/X86上使用ld.bfd链接器

LOCAL_LDFLAGS += -fuse-ld=bfd

注意:这个是编译动态库用的,为静态库使用此变量,会被忽略

 

4.15: LOCAL_ALLOW_UNDEFINED_SYMBOLS:

默认情况下,build system在编译动态库的时候遇到未定义的引用,会报错: undefined symbol?error,如果不想报错,可以将这个变量设置成true

注意:这个是编译动态库用的,为静态库使用此变量,会被忽略

 

4.16: LOCAL_ARM_MODE:

默认情况下,build system会以thumb模式生成ARM平台的二进制文件。每个指令16位。如果指定此变量为:arm。 则指令为32位。

例如:

LOCAL_ARM_MODE := arm

也可以在文件后面加.arm表示以arm模式编译此源文件,例如:

LOCAL_SRC_FILES := foo.c bar.c.arm

表示以arm模式编译bar.c,以LOCAL_ARM_MODE的模式编译foo.c

 

4.17: LOCAL_ARM_NEON:

这个变量只有在armeabi-v7a ABI的平台上才有意义,也可以在文件后面加.neon,例如:

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

含义是:foo.c按照neon编译,bar.c按照LOCAL_ARM_MODE编译,zoo.c按照arm和neon编译

注意:同时使用.arm和.neon时,.arm必须在.neon前面

 

4.18:LOCAL_DISABLE_FORMAT_STRING_CHECKS:

默认情况下,build system在编译代码的时候会对标准格式的字符串进行保护,如果在printf中有非标准格式的字符串就会报错,设置这个变量为true,可以不报错,这个变量默认是关闭的,不建议开启

 

4.19: LOCAL_EXPORT_CFLAGS:

这个变量可以记录一组 C/C++ 编译器flags,其他模块通过LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 变量使用这个模块的时候,这些flags将会添加到其他模块的 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_CFLAGS := -DBAR=2

LOCAL_STATIC_LIBRARIES := foo

include $(BUILD_SHARED_LIBRARY)

build system在编译bar.c时候,LOCAL_CFLAGS就会有-DFOO=1和-DBAR=2两个flags

另外这个变量还有传递性:例如:如果zoo依赖于bar,而bar依赖于foo,那么zoo也会继承从foo导出的所有flags

但是编译foo的时候,不会使用LOCAL_EXPORT_CFLAGS中的flags,即-DFOO=1这个flags在编译foo的时候不会使用

 

4.20 LOCAL_EXPORT_CPPFLAGS

这个变量跟4.19类似,但是只适用于C++的flags

 

4.21 LOCAL_EXPORT_C_INCLUDES

这个变量跟4.19类似,但适用于C的头文件。例如,当 bar.c 需要包括模块 foo 的头文件时,此变量很有用。

 

4.22 LOCAL_EXPORT_LDFLAGS

这个变量跟4.19类似,但适用于ld

 

4.23 LOCAL_EXPORT_LDLIBS

这个变量跟4.19类似,但是是告诉build system向编译器传递某些系统库的,每个库名称前都要加-l,这些系统库会被追加其他模块(调用这个模块的)的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)

build system在编译libbar.so时,将在链接器命令的末尾指定?-llog。这样就会告知链接器,由于libbar.so依赖于foo,因此它也依赖于系统log库。

 

4.24 LOCAL_SHORT_COMMANDS

Windows下用这个,不建议开启

 

4.25 LOCAL_THIN_ARCHIVE

编译静态库的时候用可以减小生成的二进制文件,但是这个文件不能移动到其他位置,因为里面的路径都是相对路径

注意:非静态库和预编译静态库不能用

 

4.26 LOCAL_FILTER_ASM

 

 

5、NDK提供的函数宏:

这些宏通过类似$(call <function>)的方式来得到其值,将返回文本信息。

5.1: my-dir:

$(call my-dir): 这个宏返回的是最近一次include的Makefile的路径。通常返回Android.mk所在的路径。它用来作为Android.mk的开头来定义LOCAL_PATH.

例如:

LOCAL_PATH := $(call my-dir)

注意:这个宏返回的是最近一次include的Makefile的路径。所以在Include其它Makefile后,再调用$(call my-dir)会返回其它Android.mk 所在路径。

例如:

LOCAL_PATH := $(call my-dir)

# ... declare one module

include $(LOCAL_PATH)/foo/`Android.mk`

 

LOCAL_PATH := $(call my-dir)

 

# ... declare another module

这里LOCAL_PATH最后应该是:$PATH/foo,而不是$PATH.

如果要保留第一次的LOCAL_PATH,那么只能将第一次$(call my-dir)保存在其他变量中,例如:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

 

# ... declare one module

 

include $(LOCAL_PATH)/foo/`Android.mk`

 

LOCAL_PATH := $(MY_LOCAL_PATH)

 

# ... declare another module

这样就可以将一开始LOCAL_PATH存放到MY_LOCAL_PATH里面,以备后面使用

 

5.2: all-subdir-makefiles:

返回包含在my-dir中所有子目录中的Android.mk的列表

例如:

sources/foo/Android.mk

sources/foo/lib1/Android.mk

sources/foo/lib2/Android.mk

在sources/foo/Android.mk 中使用

include $(call all-subdir-makefiles)

那么会自动include sources/foo/lib1/Android.mk和sources/foo/lib2/Android.mk

 

5.3:this-makefile:

返回当前Android.mk的路径。

 

5.4:parent-makefile:

返回当前Android.mk的上面一层的Android.mk的路径

5.5 grand-parent-makefile

返回当前Android.mk的上面两层的Android.mk的路径

 

5.6:import-module:

使用模块名寻找并include这个模块的Android.mk,例如:

$(call import-module,<name>)

 

它会从NDK_MODULE_PATH目录下寻找模块名<name>的模块并include这个模块的Android.mk。

 

6、其他变量

6.1 LOCAL_MODULE_TAGS

定义模块标签,Build system会根据标签决定哪些模块被安装

可以设置下面这些值:

user:指该模块只在user版本下才编译

eng:指该模块只在eng版本下才编译

tests:指该模块只在tests版本下才编译

optional:指该模块在所有版本下都编译

例如:

LOCAL_MODULE_TAGS := optional

 

6.2 all-java-files-under

这个宏可以用来获取java源码,例如:

$(call all-java-files-under, <src>)

获取<src>目录下的所有 Java 文件

all-java-files-under宏的定义是在build/core/definitions.mk中

 

6.3 LOCAL_PACKAGE_NAME

这个变量用来设置packet的名字

例如:

LOCAL_PACKAGE_NAME := Bluetooth

 

6.4 LOCAL_PRIVATE_PLATFORM_APIS

设置为true时,编译时可以使用sdk隐藏的api,例如

LOCAL_PRIVATE_PLATFORM_APIS := true

 

6.5 LOCAL_SDK_VERSION

编译时不可以使用sdk隐藏的api,有时一些系统的class被import后编译时说找不到这个类,就是这个原因造成的。

例如:

LOCAL_SDK_VERSION := current

LOCAL_SDK_VERSION也可以设置其他值中的一个:current system_current test_current core_current,具体含义暂时不清楚

注意:LOCAL_SDK_VERSION和LOCAL_PRIVATE_PLATFORM_APIS只能使用其中的一个,如果都不使用会报错

关于api可以分析下面几类:

Internal api:内部api,只能是sdk内部使用的,这类接口是不对外公开的

Hide api:隐藏api,在源码中使用@hide 标记的方法或者类,这类接口本意是公开的,但是目前扔不稳定,所以不建议使用

其他api:第三方app也可以使用的api

 

6.6 LOCAL_CERTIFICATE

指定用什么签名,例如:

LOCAL_CERTIFICATE := platform

表示使用platform签名

 

6.7 LOCAL_USE_AAPT2

表示是否使用aapt2工具

Aapt是android asset packaging tool的缩写,是编译和打包资源的工具,aapt2是在aapt的基础上做了优化

例如:

LOCAL_USE_AAPT2 := true

 

6.8 LOCAL_JNI_SHARED_LIBRARIES

这个变量表示编译时用到的JNI共享库

例如:

LOCAL_JNI_SHARED_LIBRARIES := libbluetooth_jni

 

6.9 LOCAL_JAVA_LIBRARIES

这个变量用来指定依赖的java共享库,这里只是依赖,不会将库打包到apk中

例如:

LOCAL_JAVA_LIBRARIES := javax.obex telephony-common services.net

 

6.10 LOCAL_STATIC_JAVA_LIBRARIES

这个变量用来指定依赖的java静态库,这里最终会将对应的库打包到apk中

例如:

LOCAL_STATIC_JAVA_LIBRARIES := \

        com.android.vcard \

        bluetooth.mapsapi \

        sap-api-java-static \

        services.net \

        libprotobuf-java-lite \

        bluetooth-protos-lite

 

6.11 LOCAL_STATIC_ANDROID_LIBRARIES

这个变量表明要调用的android的包,例如v7 v13包等

例如:

LOCAL_STATIC_ANDROID_LIBRARIES := android-support-v4

 

6.12 LOCAL_REQUIRED_MODULES

这个变量可以指定依赖的模块,一旦本模块安装,那么这个变量指定的依赖的模块也会被安装

例如:LOCAL_REQUIRED_MODULES := libbluetooth

 

6.13 LOCAL_PROGUARD_ENABLED

混淆器配置,默认是full obfuscation,即全代码混淆,disabled表示不开启混淆器

例如:

LOCAL_PROGUARD_ENABLED := disabled

 

6.14 all-Iaidl-files-under

这个宏可以获取指定目录下aidl文件

例如:

$(call all-Iaidl-files-under, <src>)

 

6.15 all-c-files-under

这个宏可以获取指定目录下C语言文件

例如:

$(call all-c-files-under, <src>)

 

6.16 all-makefiles-under

这个宏可以获取指定目录下makefile文件

例如:

$(call all-makefiles-under, <folder>)

 

6.17 BUILD_HOST_STATIC_LIBRARY

表示编译成主机上的静态库

 

6.18 BUILD_HOST_SHARED_LIBRARY

表示编译成主机上的动态库

 

6.18 BUILD_HOST_EXECUTABLE

表示编译成主机上的可执行文件

 

6.19 BUILD_JAVA_LIBRARY

表示编译成java动态库

 

6.20 BUILD_STATIC_JAVA_LIBRARY

表示编译成java静态库

 

6.21 BUILD_PACKAGE

表示编译成apk程序

 

6.22 BUILD_HOST_JAVA_LIBRARY

表示编译成主机上的java动态库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值