Android--稍解析Android.mk+函数表

习惯的三问“

一问、

什么是Android.mk
答 :是安卓上面一个用来编译系统文件的编译脚本,替代Linux下面的
Makefile。
再问?为什么要替代Makefile?
精简编译文件的语法和内容,build里面封装指令方便开发。

二问、

为什么要使用到Android.mk
猜测:原本就是make,里面加入更多适合于Android的编译的方式
命令,对于庞大的安卓源码适应Android.mk简化内部的指令使得,
我们可以清晰简便地做修改:Build System帮我们处理了很多细
节而不需要我们再关心。例如:你不需要在Android.mk中列出头文
件和外部依赖文件。NDK Build System自动帮我们提供这些信息。
这也意味着,当用户升级NDK后,你将可以受益于新的toolchain/platform
而不必再去修改Android.mk.你可以直接得益于新工具链和平台而不
需要重新修改该文件。注意:该语法和AOSP上的Android.mk的语
法很接近。这一点是故意设计用来允许应用开发人员重复利用外部库
但是编译系统中对他们的使用是不一样的。

三问、

为什么每个文件模块的编译文件都叫Android.mk,而不是其他名字?
答 : 这是因为main.mk明确指定了,以每个子目录下的Android.mk 作为模块编译的起始makfile文件。

备注:在安卓原生目录下存在一个经典的列程: /android_memory/android/development/ndk/samples/hello-jni/jni/Android.mk


Android语法内容来自于(自我整理 + 参考一下作者连接)
作者:记得柒叁贰
链接:https://www.jianshu.com/p/bee78310e420
来源:简书
学习也要尊重作者劳动成果,如有侵权联系删除

Reference:

写Android.mk文件时你应该使用或者定义的变量。你可以视具体情况定义其他的变量,但是NDK编译环境保留以下变量名:

  • LOCAL_开头的变量名(如LOCAL_MODULE) PRIVATE_,NDK_以及 APP_开头的变量名(内部使用)
    小写命名(内部使用,如my-dir) 如果你要在Android.mk文件中定义自己的变量,我们建议使用前缀MY_,

如:

  • MY_SOURCES := foo.c
    ifneq ($(MY_CONFIG_BAR),)
    MY_SOURCES += bar.c
    endif
    LOCAL_SRC_FILES += $(MY_SOURCES)

*

注:时刻记得Makefile和Android.mk语法是一样的

NDK提供的变量:
GNU Make在解析你的Android.mk文件之前由编译环境定义的一些变量。注意,在某些条件下,NDK可能会多次解析你的Android.mk文件,每一次都会为某些变量进行不同的定义。

CLEAR_VARS

指向一个脚本,取消定义在模块变量下面几乎所有的LOCAL_XXX的定义。你必须在一个新的模块下面包含这个脚本,如:
include $(CLEAR_VARS)


BUILD_SHARED_LIBRARY

指向一个脚本,收集你提供的所有LOCAL_XXX变量的信息,决定如何根据你列出 的源文件编译对应的共享库。注意,在包含这个脚本之前,你必须至少已经定义了LOCAL_MODULE和LOCAL_SRC_FILES。如:

****include ( B U I L D S H A R E D L I B R A R Y ) ∗ ∗ ∗ ∗ 注 意 , 这 会 生 成 一 个 名 为 l i b (BUILD_SHARED_LIBRARY)**** 注意,这会生成一个名为lib (BUILDSHAREDLIBRARY)lib(LOCAL_MODULE).so文件


BUILD_STATIC_LIBRARY

该变量是BUILD_SHARED_LIBRARY的一个变量,用来编译生成静态库。静态库不会拷贝到你的工程,但是可以用来生成共享库。如:

include $(BUILD_STATIC_LIBRARY)

注意:这会生成一个名为lib$(LOCAL_MODULE).a文件


PREBUILT_SHARED_LIBRARY

指向一个脚本,用来指定一个预置共享库,和BUILD_SHARED_LIBRARY以及BUILD_STATIC_LIBRARY不同的是,LOCAL_SRC_FILES的值必须是一个预置共享库的路径,而不是一个源文件。如,foo/libfoo.so。
你可以在另一个模块中使用LOCAL_PREBUILTS变量来引用预置库。(详见docs/PREBUILTS.html)


PREBUILT_STATIC_LIBRARY

和PREBUILT_SHARED_LIBRARY一样,但指定一个静态库。(详见docs/PREBUILTS.html)主要用来包含第三方库,为第三方库在Android.mk中创建模块名字,被其他库使用.使用这种编译时,LOCAL_SRC_FILES中指向一个动态库,并且最后被打包到安装包里的库会是这个动态库.


TARGET_ARCH

由AOSP指定的CPU架构名称,arm表示ARM兼容


TARGET_PLATFORM

解析Android.mk时,目标Android平台的名称。如,android-3对应Android 1.5系统镜像平台。完整的平台名称和对应的系统镜像请查阅docs/STABLE-APIS.html。


TARGET_ARCH_ABI

解析Android.mk时,目标CPU+ABI的名称。如armeabi-v7a。更多详细的内容请查阅docs/CPU-ARCH-ABIS.html。


TARGET_ABI

目标平台和abi的连接,由 ( T A R G E T P L A T F O R M ) − (TARGET_PLATFORM)- (TARGETPLATFORM)(TARGET_ARCH_ABI)定义,当你在实际设备上调试一个特定目标系统镜像时非常有用。


NDK提供的宏方法

下面时GNU Make的宏方法,必须使用$(call )的形式使用,返回文本信息。 注:Makefile文本和Android.mk是兼容的

**

my-dir

**
返回上一个包含Makefile文件的路径,通常是当前Android.mk的目录。在你的Android.mk文件起始位置定义LOCAL_PATH时很有用,如:
LOCAL_PATH := $(call my-dir)
注意:由于GNU Make的工作方式,该方法返回在解析编译脚本时最后一次包含Makefile文件的路径。在包含其他文件之后不要调用my-dir。
比如,看下面的这个例子:
LOCAL_PATH := $(call my-dir)
… declare one module
include $(LOCAL_PATH)/foo/Android.mk
LOCAL_PATH := $(call my-dir)
… declare another module

这里的问题是,第二次调用my-dir会将LOCAL_PATH定义为 ( L O C A L P A T H ) / f o o / 而 不 是 (LOCAL_PATH)/foo/而不是 (LOCALPATH)/foo/(LOCAL_PATH)。
基于上面这个原因,在一个Android.mk文件中,将额外的包含动作放在所有内容的后面,如:
LOCAL_PATH := $(call my-dir)
… declare one module
LOCAL_PATH := $(call my-dir)
… declare another module
# extra includes at the end of the Android.mk
include $(LOCAL_PATH)/foo/Android.mk
如果不方便的话,可以用一个变量保存第一次调用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


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)
那么,sources/foo/lib1/Android.mk和sources/foo/lib2/Android.mk会被自动的包含进来。
这个方法用来向编译环境提供深层嵌套的源目录结构。默认情况下,NDK只查找sources/*/Android.mk中的文件。


· this-makefile

返回当前Makefile文件的路径(如这个方法被调用的地方)。


· parent-makefile

返回包含树中父Makefile文件的路径,如包含当前Makefile的Makefile的路径。


· grand-parent-makefile

这个就不用介绍了


· import-module

该方法通过名字查找和包含另一个模块,通常的用法是:
$(call import-module,)
该方法会在你的NDK_MODULE_PATH环境变量中查找标签为<name>的模块,然后自动的将它的Android.mk包含进来。详情查看docs/IMPORT-MODULE.html。


模块定义变量

下面的变量用来向编译环境描述你的模块。你应该在include $(CLEAR_VARS)和include ( B U I L D X X X X X ) 之 间 定 义 这 些 变 量 。 如 前 所 述 , (BUILD_XXXXX)之间定义这些变量。如前所述, (BUILDXXXXX)(CLEAR_VARS)会取消定义或者清除所有这些变量。

LOCAL_PATH

这个变量表示当前文件所在的路径,必须在你的Android.mk的开始处定义,可以由下面的命令来完成:
LOCAL_PATH := $(call my-dir)
( C L E A R V A R S ) 不 会 清 除 该 变 量 , 所 以 每 一 个 A n d r o i d . m k 只 需 要 定 义 一 次 即 可 。 L O C A L M O D U L E 你 的 模 块 的 名 字 , 每 一 个 模 块 的 名 字 必 须 唯 一 且 不 含 空 格 。 你 必 须 在 包 含 (CLEAR_VARS)不会清除该变量,所以每一个Android.mk只需要定义一次即可。 LOCAL_MODULE 你的模块的名字,每一个模块的名字必须唯一且不含空格。你必须在包含 (CLEARVARS)Android.mkLOCALMODULE(BUILD_XXXX)脚本之前定义这个变量。
默认的,这个名字决定了生成文件的名字,如,名为的模块,共享库的名字为lib.so。但是,在NDK编译文件(Android.mk和Application.mk)中,你应该使用normal名字(如)去引用其他模块。你可以使用LOCAL_MODULE_FILENAME重写这个默认值:如:

LOCAL_MODULE := module_name


LOCAL_MODULE_FILENAME

这个变量是可选的,帮助你重新定义生成文件的名字。默认情况下,模块会按照Unix的一般标准生成名为lib.a的静态库或者名为lib.so的共享库。
你可以通过LOCAL_MODULE_FILENAME重新定义生成文件的名字,如:

LOCAL_MODULE := foo-version-1
LOCAL_MODULE_FILENAME := libfoo

注意:不要在LOCAL_MODULE_FILENAME中放路径或者扩展名,这些会被编译系统自动处理掉。


LOCAL_SRC_FILES

用来编译你的模块的源文件列表。只需要列出需要被传给编译器的文件,编译环境会自动帮你计算依赖关系。
所有的源文件名都是相对LOCAL_PATH的,也可以使用路径分隔符,如:
LOCAL_SRC_FILES := foo.c
toto/bar.c

注意:在编译文件中使用Unix中的前向斜杠(/),Windows中的反向斜杠()不会被正确的处理。


LOCAL_CPP_EXTENSION

这是一个可选的变量,用来指示C++源文件的文件扩展名。默认的是.cpp,但是你可以改变它,如:
LOCAL_CPP_EXTENSION := .cxx


LOCAL_C_INCLUDES

可选,相对NDK根目录的相对路径列表,在编译所有的源文件时会被添加到搜索路径后面,如:
LOCAL_C_INCLUDES := sources/foo

LOCAL_C_INCLUDES := $(LOCAL_PATH)/…/foo
他们会需要放置在LOCAL_CFLAGS / LOCAL_CPPFLAGS之前。
在使用ndk-gdb进行native调试时将自动使用LOCAL_C_INCLUDES路径。


LOCAL_CFLAGS

可选,编译C和C++源文件时的编译器flags。这个可以用来指定额外的宏定义和编译选项。
不要在Android.mk中改变优化或调试等级,通过在Application.mk中指定合适的信息就可以自动的被处理,而且会让NDK在调试时生成有用的数据文件。
注意:在android-ndk-1.5_r1中,flags只对C文件有用,C++不行。你可以使用LOCAL_CPPFLAGS为C++文件指定flags。
可以使用LOCAL_CFLAGS += -I<path>指定额外的包含路径,但是最好使用LOCAL_C_INCLUDES来实现这个,因为这些路径会在使用ndk-gdb进行native调试时使用。


LOCAL_CXXFLAGS

LOCAL_CPPFLAGS的别名,NDK后续的更新可能会移除。
LOCAL_CPPFLAGS
可选,编译C++文件时编译器flags,在编译器命令行中,他们出现在LOCAL_CFLAGS之后。
注意:在android-ndk-1.5_r1中,相应的flags会应用在C和C++文件上。为匹配整个Android编译环境,这一点已经被纠正。(现在你可以使用LOCAL_CFLAGS为C和C++源文件指定flags)


LOCAL_STATIC_LIBRARIES

需要链接到这个模块的静态库module(使用BUILD_STATIC_LIBRARY编译的)列表。只在共享库中有用。


LOCAL_SHARED_LIBRARIES

该模块在运行时需要依赖的共享库列表。在链接时需要,并在生成文件中嵌入相应的信息。


LOCAL_LDLIBS

编译你的模块时需要的额外链接flags列表。传递指定的以-l为前缀的系统库。如,下述指令会告诉链接器生成一个在加载的时候链接到/system/lib/libz.so的模块:
LOCAL_LDLIBS := -lz
查阅docs/STABLE-APIS.html获取这个版本的NDK中可用的系统库列表。


LOCAL_ALLOW_UNDEFINED_SYMBOLS

默认情况下,在编译共享数据库时会遇到未定义的引用,导致未定义符号的错误。这对在你源码中抓取log作用很大。
但是,如果考虑到某些原因需要关闭这个选项,将变量置为true即可。注意,相应的共享库可能会在运行时加载失败。


LOCAL_ARM_MODE

默认情况下,以thumb模式生成ARM目标二进制,每一个指令都是16比特宽。如果你想强制生成arm(32比特指令)模式下的模块,你可以定义这个变量为arm。如:

LOCAL_ARM_MODE := arm

你也可以通过在源文件名称后面添加后缀.arm的方式编译系统以指定的arm模式编译源文件,如:

LOCAL_SRC_FILES := foo.c bar.c.arm

上面这句会告诉编译系统以arm模式编译bar.c,但根据LOCAL_ARM_MODE的值编译foo.c。
在Application.mk文件中设置APP_OPTIM为debug也会强制生成ARM二进制文件,因为thumb代码不能很好的被调试。


LOCAL_ARM_NEON

定义这个变量为true允许在C和C++文件中使用ARM Advanced SIMD GCC(也称为NEON)指令,就像在程序集文件中使用NEON指令一样。
你只有在生成armeabi-v7a ABI对应的ARMv7指令集时定义它。由于不是所有的基于ARMv7的CPU都支持NEON指令集扩展,为了安全的在运行时使用这些代码你需要执行运行时检查。关于这点更详细的信息,请查

docs/CPU-ARM-NEON.html和docs/CPU-FEATURES.html。

你也可以通过使用后缀.neon来指定特定源文件使用NEON支持的方式来编译,如下:

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

在这里,编译器会使用thumb+neon模式编译foo.c,使用thumb模式编译bar.c,使用arm+neon编译zoo.c。后缀.neon必须放在后缀.arm后面,如果你想同时使用两者的话。


LOCAL_DISABLE_NO_EXECUTE

Android NDK r4增加了NX bit安全特性。默认为打开状态,你可以设置此变量为true,如果你真的需要关闭它的话。这个特性只在内核为ARMv6+的CPU的设备上被开启。
更多信息查阅http://en.wikipedia.org/wiki/NX_bithttp://www.gentoo.org/proj/en/hardened/gnu-stack.xml


LOCAL_EXPORT_CFLAGS

定义这个变量用来记录一组C/C++编译flags,这些会被添加到使用这个变量的模块的LOCAL_STATIC_LIBRARIES或者LOCAL_SHARED_LIBRARIES的LOCAL_CFLAGS中。
例:
'foo’module的定义:

**include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)'bar'module的定义:
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)**

在编译bar.c时会将-DFOO=1 -DBAR=2传给编译器
exported flags会被一层一层的传递,如果zoo依赖于bar,而bar依赖于foo,那么foo中的所有的flags会被传给zoo。
exported flags在当前module编译时不会被使用,在上面的例子中,在编译foo/foo.c时不会传递-DFOO=1。


LOCAL_EXPORT_CPPFLAGS

和LOCAL_EXPORT_CFLAGS一样,但是只对C++文件。


LOCAL_EXPORT_C_INCLUDES

和LOCAL_EXPORT_CFLAGS一样,但记录的是C头文件路径。可以帮助’bar.c’包含’foo’模块提供的头文件。


LOCAL_EXPORT_LDLIBS

和LOCAL_EXPORT_CFLAGS一样,记录链接器flags。导入的链接器flags会被添加到你的模块的LOCAL_LDLIBS中,这由Unix连接器的工作方式决定。
当foo是一个静态库且部分代码依赖系统库,这个变量将会很有用。LOCAL_EXPORT_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,表示它依赖于系统日志库,因为它依赖于foo。


LOCAL_FILTER_ASM

使用一个shell命令定义这个变量,用来过滤LOCAL_SRC_FILES中的或者由其生成的程序集文件。
一旦这个变量被定义,那么:
任意一个C或者C++文件都会生成为一个暂时程序集文件(而不是编译为一个obj文件)
任意一个程序集文件或者列在LOCAL_SRC_FILES中的程序集文件都会发送到LOCAL_FILTER_ASM指令中,生成另一种暂时程序集文件。
这些过滤后的程序集文件会被编译到obj文件中。
也就是说:

LOCAL_SRC_FILES := foo.c bar.S

LOCAL_FILTER_ASM := myasmfilter foo.c --1–> O B J S D I R / f o o . S . o r i g i n a l − − 2 − − &gt; OBJS_DIR/foo.S.original --2--&gt; OBJSDIR/foo.S.original2>OBJS_DIR/foo.S \ --3–> O B J S D I R / f o o . o b a r . S b a r . S − − 2 − − &gt; OBJS_DIR/foo.o bar.S bar.S --2--&gt; OBJSDIR/foo.obar.Sbar.S2>OBJS_DIR/bar.S --3–>$OBJS_DIR/bar.o

这里,"1"代表链接器,"2"代表过滤器,"3"代表汇编。过滤器必须是一个标准的shell命令,将输入文件的名字作为第一个参数,输出文件的名字作为第二个参数,如:

myasmfilter $OBJS_DIR/foo.S.original $OBJS_DIR/foo.S
myasmfilter bar.S $OBJS_DIR/bar.S


.LOCAL_MODULE_PATH / LOCAL_UNSTRIPPED_PATH

Android.mk 文件中, 还可以用LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH指定最后的目标安装路径.
不同的文件系统路径用以下的宏进行选择:
TARGET_ROOT_OUT:表示根文件系统。
TARGET_OUT:表示 system文件系统。
TARGET_OUT_DATA:表示 data文件系统。
如:


LOCAL_MODULE_PATH :=$(TARGET_ROOT_OUT)

至于LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH的区别,暂时还不清楚。


LOCAL_JNI_SHARED_LIBRARIES

定义了要包含的so库文件的名字,如果程序没有采用jni,不需要
LOCAL_JNI_SHARED_LIBRARIES := libxxx 这样在编译的时候,NDK自动会把这个libxxx打包进apk;
放在youapk/lib/目录下。除此之外,Build系统中还定义了一些函数方便在Android.mk中使用,包括:

$(call my-dir):获取当前文件夹的路径。
$(call all-java-files-under, ):获取指定目录下的所有java文件。
$(call all-c-files-under, ):获取指定目录下的所有c文件。
$(call all-Iaidl-files-under, ):获取指定目录下的所有AIDL文件。
$(call all-makefiles-under, ):获取指定目录下的所有Make文件。
$(call intermediates-dir-for, , , ,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值