详解安卓系统中的Android.mk文件_C 语言

概述
    Android.mk文件用来向编译系统描述如何编译你的源代码。更确切地说,该文件其实就是一个小型的Makefile。由于该文件会被NDK的编译工具解析多次,因此应该尽量减少源码中声明变量,因为这些变量可能会被多次定义从而影响到后面的解析。这个文件的语法允许把源代码组织成模块,每个模块属于下列类型之一:

    APK程序:一般的Android程序,编译打包生成apk文件。
    JAVA库:java类库,编译打包生成jar包文件。
    C\C++应用程序:可执行的C/C++应用程序。
    C\C++静态库:编译生产C/C++静态库,并打包成.a文件。
    C\C++共享库:编译生成共享库,并打包成.so文件,有且只有共享库才能被安装/复制到APK包中。


举例
    这里参考了网上一个通用的例子,编译简单的“Hello World”,来说明一下Android.mk编写。例如下面的文件:
1. sources/test/hello.c
2. sources/test/Android.mk
    其中“hello.c”是一个JNI共享库,实现返回“hello world”字符串的原生方法。因此,Android.mk文件内容如下:

  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
  LOCAL_MODULE := hello
  LOCAL_SRC_FILES := hello.c
  include $(BUILD_SHARED_LIBRARY) 

    解释一下这几行代码:
1. LOCAL_PATH := $(call my-dir) : 一个Android.mk文件首先必须定义好LOCAL_PATH变量,用于在开发树中查找源文件。在这个例子中,宏函数my-dir由编译系统提供,用于返回当前路径(即包含Android.mk文件的目录)。
2. include $(CLEAR_VARS):CLEAR_VARS由编译i系统提供,指定让GNU MAKEFILE清除除了LOCAL_PATH变量外的许多LOCAL_***变量(例如:LOCAL_MODULE、LOCAL_SRC_FILES等)。这是非常有必要的,因为所有的编译文件都在同一个GUN MKAE执行环境中,所有的变量都是全局变量,不清除容易引起解析错误。
3. LOCAL_MODULE := hello:LOCAL_MODULE变量必须定义,用来标识在Android.mk文件描述的每一个模块。而且名称必须是唯一的,并且不能包含空格。编译系统会自动产生合适的前缀和后缀,比如一个被命名为hello的共享库模块,将会生成libhello.so文件。如果把库命名为libhello,编译系统将不会添加任何lib前缀,也会生成libhello.so文件。
4. LOCAL_SRC_FILES := hello.c:LOCAL_SRC_FILES变量必须包含将要编译打包进模块中的源代码文件。
5. include $(BUILD_SHARED_LIBRARY):BUILD_SHARED_LIBRARY是编译系统提供的变量,指向一个GNU Makefile脚本(应该就是build/core目录下的shared_library.mk),负责收集自从上次调用include $(CLEAR_VARS)以来,定义在LOCAL_***变量中的所有信息,并且决定编译什么,如何正确地去做,并根据其规则生成静态库。
6. 解释一下Android.mk里变量定义字符":="。“:=”类似于c中的宏,即在定义处明确展开,完全进行文本替换。

模块描述变量
     下面的变量用于向系统描述我们自己的模块,它应该定义在include $(CLEAR_VARS)和include $(BUILD_***)之间。正如前面讲述的那样,$(CLEAR_VARS)是一个脚本,清除所有这些变量,除非在描述中显示注明。
1. LOCAL_PATH:这个变量用于给出当前文件的路径,必须在Android.mk的开头定义,可以这样使用:LOCAL_PATH := $(call my-dir),这样这个变量不会被$(CLEAR_VARS)清除,因为每个Android.mk只需要定义一次(即使一个文件中定义了多个模块的情况下)。
2. LOCAL_SRC_FILES:当前模块包含的所有源代码文件。
3. LOCAL_MODULE:当前模块的名称,这个名称应当是唯一的,并且不能包含空格。模块间的依赖关系就是通过这个名称来引用的。
4. LOCAL_MODULE_CLASS:标识所编译模块最后放置的位置。ETC表示放置在/system/etc.目录下,APPS表示放置在/system/app目录下,SHARED_LIBRARIES表示放置在/system/lib目录下。如果具体指定,则编译的模块不会放到编译系统中,最后会在out对应product的obj目录下的对应目录中。
5. LOCAL_SRC_FILES:这是要编译的源代码文件列表。只要列出要传递给编译器的文件即可,编译系统会自动计算依赖关系。源代码文件路径都是相相对于LOCAL_PATH的,因此可以使用相对路径进行描述。
6. LOCAL_JAVA_LIBRARIES:当前模块依赖的Java共享库,也叫Java动态库。例如framework.jar包。
7. LOCAL_STATIC_JAVA_LIBRARIES:当前模块依赖的Java静态库,在Android里,导入的jar包和引用的第三方工程都属于Java静态库。
8. LOCAL_STATIC_LIBRARIES:当前模块在运行时依赖的静态库的名称。
9. LOCAL_SHARED_LIBRARIES:当前模块在运行时依赖的动态库的名称。
10. LOCAL_C_INCLUDES:c或c++语言需要的头文件的路径。
11. LOCAL_CFLAGS:提供给C/C++编译器的额外编译参数。
12. LOCAL_PACKAGE_NAME:当前APK应用的名称。
13. LOCAL_CERTIFICATE:签署当前应用的证书名称。
14. LOCAL_MODULE_TAGS:当前模块所包含的标签,一个模块可以包含多个标签。标签的值可能是eng、user、debug、development、optional。其中,optional是默认标签。
15. LOCAL_DEX_PREOPT:apk的odex优化开关,默认是false。

    除此之外,Build系统中还定义了一些函数方便在Android.mk中使用,包括:
1. $(call my-dir):获取当前文件夹的路径。
2. $(call all-java-files-under, <src>):获取指定目录下的所有java文件。
3. $(call all-c-files-under, <src>):获取指定目录下的所有c文件。
4. $(call all-Iaidl-files-under, <src>):获取指定目录下的所有AIDL文件。
5. $(call all-makefiles-under, <folder>):获取指定目录下的所有Make文件。
6. $(call intermediates-dir-for, <class>, <app_name>, <host or target>, <common?>):获取Build输入的目标文件夹路径。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
mk
android.mk详解、android.mk文件详解、android系统架构详解、android系统详解、android 获取系统语言,以便于您获取更多的相关知识。

时间: 2024-12-31 08:04:10

详解安卓系统中的Android.mk文件_C 语言的相关文章

详解Linux系统中的文件名和文件种类以及文件权限

Linux文件种类与副文件名 一直强调一个概念,那就是:任何装置在Linux底下都是文件, 不仅如此,连资料沟通的介面也有专属的文件在负责-所以,你会?解到,Linux的文件种类真的很多- 除了前面提到的一般文件(-)与目录文件(d)之外,还有哪些种类的文件呢? * 文件种类: 我们在刚刚提到使用'ls -l'观察到第一栏那十个字元中,第一个字元为文件的类型. 除了常见的一般文件(-)与目录文件(d)之外,还有哪些种类的文件类型呢? * 正规文件(regular file ):       就是

详解C++编程中数组的基本用法_C 语言

可以使用数组下标操作符 ([ ]) 访问数组的各个元素. 如果在无下标表达式中使用一维数组,组名计算为指向该数组中的第一个元素的指针. // using_arrays.cpp int main() { char chArray[10]; char *pch = chArray; // Evaluates to a pointer to the first element. char ch = chArray[0]; // Evaluates to the value of the first e

详解C++编程中断言static_assert的使用_C 语言

断言和用户提供的消息 C++ 语言支持可帮助您调试应用程序的三个错误处理机制:#error 指令.static_assert 关键字和 assert (CRT) 宏.所有的三种机制都会发出错误消息,其中两个还会测试软件断言.软件断言指定在程序的某个特定点应满足的条件.如果编译时断言失败,编译器将发出诊断消息和编译错误.如果运行时断言失败,操作系统将发出诊断消息并关闭应用程序. 备注 应用程序的生存期由预处理.编译和运行时阶段组成.每个错误处理机制都会访问在这三个阶段之一中可用的调试信息.若要有效

详解Linux系统中md5sum命令的用法

  这篇文章主要介绍了详解Linux系统中md5sum命令的用法,用来处理MD5验证的相关操作,需要的朋友可以参考下 MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改.MD5全称是报文摘要算法(Message-Digest Algorithm 5),此算法对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的"指纹"(或称"报文摘要"),不同的文件产生相 同的报文摘要的可能性是非常非常之小的. 在linux或Unix上,

详解Linux系统中的root权限控制

  在Linux操作系统中,root的权限是最高的,也被称为超级权限的拥有者.普通用户无法执行的操作,root用户都能完成,所以也被称之为超级管理用户. 在系统中,每个文件.目录和进程,都归属于某一个用户,没有用户许可其它普通用户是无法操作的,但对root除外.root用户的特权性还表现在root 可以超越任何用户和用户组来对文件或目录进行读取.修改或删除(在系统正常的许可范围内);对可执行程序的执行.终止;对硬件设备的添加.创建和移除等; 也可以对文件和目录进行属主和权限进行修改,以适合系统管

详解Linux系统中Oracle数据库程序的启动和关闭方式_oracle

在单机环境下,要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle Oracle数据库有以下几种启动方式: 1. startup nomount 非安装启动,这种方式启动下可执行:重建控制文件.重建数据库 读取init.ora文件,启动instance,即启动SGA和后台进程,这种启动只需要init.ora文件. 2. startup mount dbname 安装启动,这种方式启动下可执行: 数据库日志归档. 数据库介质恢复. 使数据文件联机或脱机, 重新

详解Linux系统中的守护进程

守护进程daemon,是生存期较长的一种进程.它们常常在系统自举时启动,仅在系统关闭时才终止.因为它们没有控制终端,所以说它们是在后台运行的.UNIX系统有很多守护进程,它们执行日常事务活动. 1.系统自举 自举(bootstrapping)一词来自于人都是靠自身的"自举"机构站立起来的这一思想.计算机必须具备自举能力将自己所有的元件激活,以便能完成加载操作系统这一目的,然后再由操作系统承担起那些单靠自举代码无法完成的更复杂的任务. 自举只有两个功能:加电自检和磁盘引导. 加电自检:当

详解Linux系统中的文件权限设置

你要明白的第一件事是文件权限可以用来干什么.当你设置一个分组的权限时发生了什么?让我们将其展开来说,这个概念就真的简单多了.那到底什么是权限?什么是分组呢? 你可以设置的3种权限: 1.读 - 允许该分组读文件(用r表示) 2.写 - 允许该分组写文件(用w表示) 3.执行 - 允许该分组执行(运行)文件(用x表示) 为了更好地解释这如何应用于一个分组,例如,你允许一个分组可以读写一个文件,但不能执行.或者,你可以允许一个分组读和执行一个文件,但不能写.甚至你可以允许一个分组有读.写.执行全部的

详解Linux系统中配置静态路由的方法

  主机只有一块网卡的时候,不会涉及到默认路由和静态路由的问题.两块网卡时,也可以一块配置有网关(默认路由走这个网卡),另外一块只配置IP和掩码确认(该主机同网络的可以互通).不过在稍大型的.有多网段的环境里就需单独进行默认路由和静态路由的配置了. 一.需求 目前有如下的一个网络,主机有两个网卡,两个网段分别是是业务地址eth0和管理地址eth1. 业务地址段为:192.168.3.0/24段 管理地址段:10.212.52.0/24段 防火墙段:10.211.6.0/24段 现在的需求是,默认