Android源码分析 十月 20, 2016 chaossss No comments

Android.mk

什么是Android.mk

Android.mk文件用于向编译系统描述C/C++源文件,更准确地说:

  1. Android.mk是一个将会被编译系统解析一次甚至多次的小型GNU makefile片段。因此,你应该尽可能最小化声明的变量数,并且保证在解析过程中没有任何变量是未定义的。

  2. Android.mk的语法允许用户将C/C++源文件以**module**为单位组织,一个module将包含以下内容:

  • 静态库,.a文件
  • 动态库(共享库),.so文件

动态库会被安装/拷贝到应用包中;静态库可以用于生成动态库。

此外,用户可以在Android.mk中定义一个或多个module,也可以在多个module中使用相同的C/C++源文件

  1. 编译系统会为用户解决非常多小麻烦,例如:用户不需要在已生成的文件间列出头文件或其他的依赖关系。这也就意味着当NDK被更新,你甚至不需要修改Android.mk文件就能获得新的工具链或平台支持的好处。

Note : 这些语法非常接近于分布在ASOP中的Android.mk文件,尽管在不同的编译系统实现中对它们的使用各不相同,但有意地把它设计成这样能简化开发者重用外部库代码的过程。

一个例子

在详细介绍Android.mk的语法前,不妨先看看下面这个”hello JNI”的例子,假设这个项目文件在apps/hello-jni/project,那么我们可以认为:

  • src目录包含该Android示例项目的Java源码
  • jni目录包含该示例项目的C/C++源码,假设为jni/hello-jni.c
  • jni/Android.mk文件则向NDK的编译系统描述了动态库,文件内容为:

现在我们来逐行解释其中意义:

Android.mk文件必须以LOCAL_PATH变量的定义开始,LOCAL_PATH变量用于在开发树(development tree)中定位源文件。在本示例中,由编译系统提供的宏函数(macro function)用于返回当前目录的路径(例如包含Android.mk文件的目录)

CLEAR_VARS变量由编译系统提供的指向某个特定的GNU Makefile文件,该GNU Makefile文件将为用户清理除了LOCAL_PATH以外的许多LOCAL_XXX变量(例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等……)。需要CLEAR_VARS变量的原因是:所有编译控制文件都将在一个独立的GNU make指令执行上下文中被解析,在这个过程中所有的变量都是全局变量。

The LOCAL_MODULE variable must be defined to identify each module you describe in your Android.mk. The name must be unique and not contain
any spaces. Note that the build system will automatically add proper prefix and suffix to the corresponding generated file. In other words,
a shared library module named ‘foo’ will generate ‘libfoo.so’.

LOCAL_MODULE变量必须在Android.mk中被定义,以用于区分用户描述的每一个modulemodule的名字不能重复,且不能包含空格。需要注意的是:编译系统会自动为相应的生成文件添加合适的前缀和后缀。这样说可能有点抽象,举个例子:一个名为foo的动态库module生成后的名称为:libfoo.so

IMPORTANT NOTE:
If you name your module ‘libfoo’, the build system will not add another ‘lib’ prefix and will generate libfoo.so as well.
This is to support Android.mk files that originate from the Android platform sources, would you need to use these.

重要的提示:如果用户自己将module命名为libfoo,编译系统则不会添加lib前缀,所以生成的名称还是libfoo.so

LOCAL_SRC_FILES变量必须包含一个列举将要被编译和聚合到某个module中的C/C++源文件的列表。需要注意的是:用户不应该列举头文件和已包含的文件,因为编译系统会自动地推断需要哪些依赖;用户只需要列出将会被直接地传递给编译器的C/C++源文件,然后坐享其成即可。

需要注意:C++源文件的默认拓展名是.cpp,当然,用户也可以通过定义LOCAL_CPP_EXTENSION变量的值来指定其他拓展名。在定义LOCAL_CPP_EXTENSION变量的时候千万不要忘了**.**噢,例如拓展名应该是.cxx,而不是cxx

The BUILD_SHARED_LIBRARY is a variable provided by the build system that points to a GNU Makefile script that is in charge of collecting all the
information you defined in LOCAL_XXX variables since the latest ‘include $(CLEAR_VARS)’ and determine what to build, and how to do it
exactly. There is also BUILD_STATIC_LIBRARY to generate a static library.

There are more complex examples in the samples directories, with commented Android.mk files that you can look at.

BUILD_SHARED_LIBRARY变量用于指向编译系统提供的一个GNU Makefile脚本,该脚本负责收集所有从最近的include $(CLEAR_VARS)开始定义的LOCAL_XXX变量的信息,判断应该编译什么以及如何准确地得到编译的输出。当然,还有BUILD_STATIC_LIBRARY变量用于生成静态库。

在示例目录里还有一些更复杂的示例,这些Android.mk文件都添加了注释,你可以对照着学习。

语法参考:

This is the list of variables you should either rely on or define in an Android.mk. You can define other variables for your own usage, but
the NDK build system reserves the following variable names:

下面列举的变量都是你在编写Android.mk时会依赖或定义的,你也可以为了方便定义其他的变量,但你需要注意的是,下列变量名由编译系统保留(即你不能自己定义下列名称):

  • 以LOCAL_开头的名称(例如:LOCAL_MODULE)
  • 以PRIVATE_、NDK_或APP_开头的名称(内部使用)
  • 小写的名称 (内部使用, 例如my-dir)

If you need to define your own convenience variables in an Android.mk file, we recommend using the MY_ prefix, for a trivial example:

如果你需要在Android.mk中自定义变量,我推荐你使用MY_前缀,下面举个简单的例子:

介绍完规则不妨就来看看编译系统提供的变量吧:

由于后面都是些规则,类似于API文档,要用的时候自己查就是了,我也懒得翻译了。

发表评论