【Android源码 栏目提醒】:网学会员在Android源码 频道为大家收集整理了“Android mk文件语法规范 - 技术总结“提供大家参考,希望对大家有所帮助!
Android.mk文件语法规范 译者ChrixLee 2010.5.12 序言 ------------- 此文档旨在描述
Android.mk文件的语法
Android.mk文件为
Android NDK原生开发描述了你C/C源文件。
为了明白下面的内容你必须已经阅读了docs/OVERVIEW.TXT的内容它解释了
Android.mk文件扮演的角色 和用途。
概述 --------- 写一个
Android.mk文件是为了向生成系统描述你的源代码。
更明确的说 - 这个文件实际上是GNU Make文件的一小片段它会被生成系统解析一次或多次。
因此你应该在
Android.mk里尽量少地声明变量而不要误以为在解析的过程中没有任何东西被定义。
- 该文件的语法的明的人为了让你能将你的源代码组织为组件module.一个组件指的是下面的一项 - 一个静态库static library - 一个共享库shared library 只有一个动态库会被安装/拷贝至你的application package中。
但是静态库可用来生成动态库。
你可以在每个
Android.mk文件定义一个或多个组件并且我可以在几个组件中使用相同的源文件。
- 生成系统为你处理了一些琐碎之事。
比如在你的
Android.mk里你不须要列出头文件或列出生成的文件之间的明确认依赖关系。
NDK生成系统会为你自动生成。
这也意味着当更新至新的NDK版本时你能得到新的工具链/平台支持toolchain/platform support的好处而无须修改你的
android.mk文件。
需要注意的是此语法与完全开源的
Android平台的
Android.mk文件的语法非常相似但使用它们的生成系统的实现不同这个为了让开发者能更容易的复用“外部”库的源代码。
简单例子 --------------- 在详细描述语法之前让我们探究一个简单的“hello JNI”例子它的文件位于 apps/hello-jni/projec 这里我们能看到 - 放有Java源文件的src文件夹。
- 放有本地源文件即jni/hello-jni.c的jni文件夹。
这个源文件实现一个简单的共享库。
这个共享库有一个本地方法native method它将一个字符串返回给虚拟机应用著即Java层应用程序 - jni/Anroid.mk文件为NDK生成系统描述了这个共享库。
它的内容为 ---------- cut here ------------------ LOCAL_PATH : call my-dir include CLEAR_VARS LOCAL_MODULE : hello-jni LOCAL_SRC_FILES : hello-jni.c include BUILD_SHARED_LIBRARY ---------- cut here ------------------ 现在让我们逐行解释 LOCAL_PATH : call my-dir 每个
Android.mk文件都必须以定义LOCAL_PATH变量开始。
其目的是为了定位源文件的位置。
在这个例子生成系统提供的宏函数macro function‘my-dir用来返回当前路径即放有
Android.mk文件的文件夹 include CLEAR_VARS CLEAR_VARS变量是生成系统提供的它指向一个特殊的GNU Makefile.这个Makefile将会为你自动清除许多名为LOCAL_XXX的变量比如LOCAL_MODULELOCAL_SRC_FILESLOCAL_STATIC_LIBRARIES等但LOCAL_PATH是例外它不会被清除。
这些变量的清除是必须的因为所有的控制文件是在单一的GNU make执行环境中解析的在这里所有的变量都是全局的。
LOCAL_MODULE : hello-jni 为了在你的
Android.mk文件标识每个组件必须定义LOCAL_MODULE变量。
这个名字必须要唯一的并且不能包含空格。
注意生成系统会自动地为相应生成的文件加入前缀或后缀。
换言之一个名叫foo的共享库组件会生成libfoo.so. 重要注意事项 如果你把组件取名为‘libfoo生成系统将不会加上‘lib前缀还是 生成libfoo.so。
这是为了支持源于
Android平台源代码的
Android.mk文件。
LOCAL_SRC_FILES : hello-jni.c LOCAL_SRC_FILES变量必须包含一系列将被构建和组合成组件的C/C源文件。
注意你不需要列出头文件或include文件因为生成系统会为你自动计算出源文件的依赖关系。
仅仅列出那些将直接传给编译器的源文件足矣。
注意默认的C源文件的扩展名是‘.cpp。
但你可以通过定义LOCAL_DEFAULT_EXTENSION来指定一个扩展名。
别忘了扩展名开始的那一点比如‘.cxx’能行但‘cxx不行。
include BUILD_SHARED_LIBRARY 生成系统提供的BUIL_SHARED_LIBRARY变量指向一个GNU Makefile脚本这个脚本主管收集在最近的一次include CLEAR_VARS著即清除本地变量之后你所定义的LOCAL_XXX变量的信息并决定生成什么如何准确的生成。
BUILD_STATIC_LIBRARY可生成一个静态库。
There are more complex examples under apps/ with commented
Android.mk files that you can look at. 在apps文件下有一些复杂点的例子它带有注释的
Android.mk文件以供你学习。
参考 ----------- 以下列出你在
Android.mk里应该依赖或定义的变量。
你能定义其它变量但下列的变量名是由NDK生成系统保留的。
- 以LOCAL_ 开头的变量名 比如LOCAL_MODULE - 以PRIVATE_ NDK_ 或 APP_ 内部使用开头的量名 _ 小写字母变量名内部使用如 my-dir. 如果你需要在
Android.mk里定义方便自己使用的变量名我们建议使用MY_ 前缀 如下面一个简单例子: ---------- cut here ------------------ MY_SOURCES : foo.c ifneq MY_CONFIG_BAR MY_SOURCES bar.c endif LOCAL_SRC_FILES MY_SOURCES ---------- cut here ------------------ So here we go: NDK提供的变量 - - - - - - - - - - - - - - 下列的这些GNU Make变量是在你的
Android.mk被解析之前就被生成系统事先定义的了.注意在某些情况下NDK可能会多次解析你的
Android.mk每次对其中一些变量的定义不同。
CLEAR_VARS 指向一个生成脚本这个脚本取消几乎所有LOCAL_XXX变量的定义译者注除了LOCAL_PATH。
在开始描述一个新的组件之前你必须include这个脚本e.g. include CLEAR_VARS BUILD_SHARED_LIBRARY 指向一个生成脚本这个脚本通过LOCAL_XXX变量收集关于组件的信息并决定如何根据你列出来的源文件生成目标分享库。
注意在include这个脚本文件之前你必须至少已经定义了LOCAL_MODULE和LOCAL_SRC_FILES。
用法举例 include BUILD_SHARED_LIBRARY 注意这会生成一个名为 libLOCAL_MODULE.so的文件。
译者注BUILD_SHARED_MODULE为文件名 BUILD_STATIC_LIBRARY 与BUILD_SHARED_LIBRARY类似但用来生成目标静态库。
静态库不会被拷贝至你的project/packages文件夹下但可用来生成分享库参考 LOCAL_STATIC_LIBRARIES和LOCAL_STATIC_WHOLE_LIBRARIES将在后面描述 用法示例 include BUILD_STATIC_LIBRARY 注意这会生成一个方件名叫libLOCAL_MODULE.a TARGET_ARCH 目标CPU的名字在完整的
Android开源代码的生成中指定。
对于基于ARM兼容的CPU它被指定为arm与CPU架构的修订无关。
TARGET_PLATFORM 当解析该
Android.mk文件时用它来指定Andoid目标平台的名称。
譬如
android-3与
Android 1.5系统镜像相对应。
若要了解所有的平台名称及其相应的
Android系统镜像请阅读docs/STABLE-APIS.TXT TARGET_ARCH_ABI 当解析该
Android.mk时CPUABI的名称。
目前只有一个值。
译者注ABIApplication Binary Interface二进制应用程序接口 armeabi For Armv5TE armeabi 指定Armv5TE 注意到NDK 1.6_r1为止仅简单的定义这个变量为arm。
但为了更好地配合
Android平台的内部使用该值已重定义。
关于ABI与相应的兼容问题更多详情请阅读docs/CPU-ARCH-ABIS.TXT 未来的NDK版本将会引入其它的平台的ABI并会有不同的名称。
注意所有基于ARM的ABI会使TARGET_ARCH定义为arm但可能拥有不同的TARGET_ARCH_ABI TARGET_ABI 目标平台与abi的连接它实际上被定义为 TARGET_PLATFORM-TARGET_ARCH_ABI 当你想在一个真实的装置上测试特定的目标系统镜像时它就很有用了。
默认下它的值为
android-3-armeabi 在
Android NDK 1.6_r1及之前的版本它的默认值为
android-3-arm NDK提供的宏函数: ---------------------------- 以下是一些GNU Make的宏‘函数’必须通过这样的形式调用call 。
函数返回文本信息。
my-dir 返回放置当前
Android.mk的文件夹相对于NDK生成系统根目录的路径。
可用来 在
Android.mk的开始处定义LOCAL_PATH的值 LOCAL_PATH : call my-dir 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 那么它将会自动地includesources/foo/lib1/
Android.mk和sources/foo/lib2/
Android.mk 这个函数能将深层嵌套的代码文件夹提供给生成系统。
注意默认情况下NDK仅在source//
Android.mk里寻找文件。
this-makefile 返回当前Makefile译者注指的应该是GNU Makefile的路径即这个函数是在哪里调用的 parent-makefile 返回在列入树inclusion tree中的父makefile的路径。
即包含当前makefile的那个makefile的路径。
grand-parent-makefile 猜猜看...译者注原文为Guess what... 组件描述相关的变量 - - - - - - - - - - 以下的变量是用来向生成系统描述你的组件的。
你应该在include CLEAR_VARS 和include BUILD_XXXXX之间定义其中的一些变量。
正如在前面所说的CLEAR_VARS 是一个将会取消所有这些变量的脚本除非在对变量的描述时有显式的说明。
LOCAL_PATH 这个变量用来设置当前文件的路径。
你必须在
Android.mk的开始处定义它比如 LOCAL_PATH : call my-dir 这个变量不会被CLEAR_VARS消除所以每个
Android.mk仅需一个定义以防你在 同一个文件里定义几个组件。
LOCAL_MODULE 定义组件的名称。
对于所有的组件名它必须是唯一且不能包含空格。
在include BUILD_XXX之前你必须定义它。
这个组件名决定生成的文件译者注即库名。
比如lib即这个组件的名称 为。
但是在你的NDK生成文件不管是
Android.mk还是Application.mk中 你只能通过‘正常’的名称如来引用其它的组件。
LOCAL_SRC_FILES 用它来定义所有用来生成组件的源文件。
仅须列出传给编译器的文件因为 生成系统会自动地计算它们的相互依赖关系。
注意所有文件名都是相对于LOCAL_PATH的你可以用到路径组件path component 如 LOCAL_SRC_FILES : foo.c 译者注‘’为连接符 toto/bar.c LOCAL_CPP_EXTENSION 这是一个可选的变量可用它来指明C源文件的扩展名。
默认情况下是.cpp 但你可以改变它。
比如 LOCAL_CPP_EXTENSION : .cxx LOCAL_C_INCLUDES 一个相对于相对于NDK根目录可选的路径名单当编译所有的源文件CC和汇编时 它将被添加进include搜索路径。
例如 LOCAL_C_INCLUDES : sources/foo 或者甚至 LOCAL_C_INCLUDES : LOCAL_PATH/../foo LOCAL_CFLAGS 一个可选的编译标记集在生成C与C源文件时将解析它。
对指定额外的宏定义或编译选项很有用。
重要不要试图改变你
Android.mk里的optimization/debuggin level通过在你的
Android.mk里指定合适的信息它将被自动处理并使NDK生成调试时可用的有用的数据文件。
注意在
android-ndk-1.5_r1相应的标记flags只适用于C源文件对C源文件并不适用。
为了适用于完整的
Android生成系统的特性已作了修正。
现在你可以使用LOCAL_CPPFLAGS为C文件指定标记 LOCAL_CXXFLAGS LOCAL_CPPFLAGS的别名。
注意不建议使用这个变量因为在未来的NDK版本中它可能会消失。
LOCAL_CPPFLAGS 一个可选的编译标记集仅在生成C源文件时解析它。
在编译器的命令行里 它将在LOCAL_CFLAGS之后出现。
注意在
android-ndk-1.5_r1相应的标记flags适用于C与C源文件。
为了适用于完整的
Android生成系统的特性已作了修 正。
现在你可以使用LOCAL_CFLAGS为C和C源文件指定标记 LOCAL_STATIC_LIBRARIES 一份static libraries组件的名单以BUILD_STATIC_LIBRARY的方式生成它将被连接到欲生成的组件上。
这仅在生成shared library组件时有意义。
译者注将指定的一个或多个static library module转化为一个shared library module LOCAL_SHARED_LIBRARIES 一份该组件在运行期依赖于它的shared libraries 组件。
在连接时间link time里与及为该生成的文件嵌入相应的信息都要用到它。
注意它并不将这份组件名单添加入生成图表build graph。
即在你的
Android.mk里你仍应该将它们加入到你的应用程序要求的组件。
LOCAL_LDLIBS 一份能在生成你的组件时用到的额外的连接器标记linkerflags的名单。
在传递有“-l”前缀的特殊系统库的名称时很有用。
比如下面的语句会告诉连接器在装载时间load time里生成连接到/system/lib/libz.so的组件。
LOCAL_LDLIBS : -lz 若想知道在这个NDK版本可以连接哪些暴露的系统库exposed system libraries请参见docs/STABLE-APIS。
LOCAL_ALLOW_UNDEFINED_SYMBOLS 缺省值情况下当尝试生成一个shared library遇到没有定义的引用时会导致“undefined symbol”error。
这对在你的源代码里捕捉bugs有很大的帮助。
但是因为一些原因你须要disable这个检查将这个变量设置为true’。
注意相应的shared library可能在运行期装载失败。
LOCAL_ARM_MODE 缺省值情况下ARM目标二进制将会以‘thumb’模式生成这时每个指令都是16-bit宽的。
如果你想强迫组件的object文件以‘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二进制 代码。
这是因为工具链的调度器有bugs它对thumb码的处理不是很好。