amdroid源码部分编译-了解Android编译命令

工欲善其事,必先利其器。 想要深入学习Android源码,首先必须掌握Android编译命令。

一、简介

关于Android Build系统,这个话题准备了很久,但是很久没有写出来,所以决定分享给大家。 先看下面的指令,相信编译过Android源码的人都比较熟悉。

source setenv.sh
lunch
make -j12

记得刚接触Android的时候,同事告诉我,用前面的命令就可以编译Android源码。 虽然命令很短,但是我记不住或者忘记了命令。 每次编译的时候都需要看一下我的云笔记。 我总是记不住指示。 后来我决定仔细研究一下这个命令的含义。 知道它是什么,就需要知道它为什么,这样才能更深层次地理解和记忆,这样才能与自己的知识体系有一个完美而牢固的联系,也许会有意想不到的收获。 果然,下面给大家分享一下在学习Android Build(编译)系统的过程中,上述指令的含义。

2. 编译命令

编译环境准备好后,编译Android源码的第一步是source build/envsetup.sh,其中source命令用于运行shell脚本命令,其作用相当于“.”,所以这个命令也相当于 .build/envsetup.sh。 在文件 envsetup.sh 中,声明了当前会话终端可用的命令。 这里需要注意的是当前会话终端,这意味着每次打开新终端时都必须再次执行该命令。 一开始我不明白为什么新打开的终端不能直接执行make命令,到这里终于明白了。

接下来解释一下本文开头引用的命令:

source setenv.sh  //初始化编译环境,包括后面的lunch和make指令
lunch  //指定此次编译的目标设备以及编译类型
make  -j12 //开始编译,默认为编译整个系统,其中-j12代表的是编译的job数量为12。

所有编译命令都可以在envsetup.sh文件中找到对应的函数,比如上面提到的命令lunch和make,必须在该文件中找到

function lunch(){
    ...
}
function make(){
    ...
}

源envsetup.sh,需要cd到setenv.sh文件所在路径执行,该路径可能是build/envsetup.sh,也可能是integrate/envsetup.sh,也不排除有些厂家会各自封装了.sh脚本,但核心思想是一致的。

具体实现这里不再赘述,下面总结一下各指令的用法和作用。

2.1 代码编译及编译指令解释

在源代码树的根目录下编译

毫米

编译当前路径下的所有模块,但不包含依赖项

嗯[模块路径]

编译指定路径下的所有模块,但不包含依赖

MMA

编译当前路径下的所有模块,包括依赖

mmma [模块路径]

编译指定路径下的所有模块,并包含依赖

制作[模块名称]

不带参数,表示编译整个Android代码

部分模块的编译说明如下:

模块 make 命令 mmm 命令

在里面

进行初始化

mmm 系统/核心/init

受精卵

制作应用程序进程

mmm 框架/base/cmds/app_process

系统服务器

提供服务

mmm 框架/基础/服务

java框架

制作框架

mmm 框架/基础

框架资源

制作框架资源

mmm 框架/基础/核心/res

jni框架

制作 libandroid_runtime

mmm 框架/基础/核心/jni

活页夹

制作libbinder

mmm 框架/native/libs/binder

上述mmm命令也适用于mm/mma/mmma。 编译系统采用增量编译,只有发生变化的目标文件才会被编译。 当需要重新编译所有相关模块时,需要在编译命令后减少参数-B,如make -B [module_name],或者mm -B [module_path]。

尖端:

2.2 代码搜索搜索命令解释

正则表达式

对所有 C/C++ 文件执行搜索操作

jgrep

对所有 Java 文件执行搜索操作

格列普

所有 Gradle 文件都执行搜索操作

mangrep [关键字]

源码编译安装的好处_源码编译deb_amdroid源码部分编译

所有AndroidManifest.xml文件都执行搜索操作

mgrep [关键字]

所有Android.mk文件都执行搜索操作

sepgrep [关键字]

对所有 sepolicy 文件执行搜索操作

resgrep [关键字]

对所有本地 res/*.xml 文件执行搜索操作

sgrep [关键字]

对所有资源文件执行搜索操作

上述指令用法的最终实现方法是基于grep指令,各指令的用法格式如下:

xgrep [keyword]  //x代表的是上表的搜索指令

例如,要搜索所有AndroidManifest.xml文件中launcher关键字所在文件的具体位置,指令

mangrep launcher

再比如,在所有Java代码中搜索包含zygote的文件

jgrep zygote

再比如,搜索所有system_app的selinux权限信息

sepgrep system_app

Tips:Android的源代码非常庞大。 使用grep直接搜索代码不仅笨拙且耗时,而且会得到很多无意义且令人困惑的结果。 根据具体需要选择合适的代码搜索命令amdroid源码部分编译,可以节省代码搜索时间,提高搜索结果的准确性,方便定位目标代码。

2.3 导航指令 导航指令说明

克鲁特

切换到Android根目录

项目组

切换到项目根目录

godir [文件名]

跳转到包含文件的目录

Tips:当一个文件每次修改后都需要编译时,执行cproj后会跳转到当前模块的根目录,也就是Android.mk文件所在的目录,然后执行mm命令进行编译目标模块; 当深入源码级别后,需要返回到根目录,使用croot命令来完成; 另外,cd - 命令可用于快速切换到下一个目录。

2.4 信息查询查询命令解释

查询所有命令帮助信息

查找makefile

查询当前目录所在项目的Android.mk文件路径

打印午餐菜单

查询午餐可用产品

打印配置

查询各种编译变量的值

盖顶

查询Android源码根目录

获取目标架构

获取TARGET_ARCH值

2.5 其他说明

上面只列出了比较常用的指令,还有其他指令,不同的build编译系统支持的指令可能会有一些差异。 当你忘记这种编译指令时,可以通过执行hmm来查询该指令的帮助信息。

最后列出两个比较常用的命令:

3、编译系统

Android编译系统是Android源码的一部分,用于编译Android系统、Android SDK以及相关文档。 编译系统由Make文件、Shell和Python脚本组成,其中最重要的是Make文件。 关于构建系统,请参阅了解Android构建系统。

3.1 Makefile分类

整个Build系统的Make文件分为三类:

3.2 编译产品

make编译出来的产品都位于/out目录下。 在该目录中,主要关注以下目录:

在/out/target/product/[product_name]目录下,有几个重量级的镜像文件:

当然还有boot.img、reocovery.img等镜像文件,这里就不介绍了。

3.3 Android.mk分析

源码树中每个模块的所有文件一般都有自己的文件夹,在模块的根目录下有一个名为“Android.mk”的文件。 编译系统以模块为单位进行编译。 每个模块都有一个唯一的模块名称。 一个模块可以依赖于多个其他模块。 模块之间的依赖关系通过模块名称来引用。 也就是说,当模块需要依赖jar包或apk时,必须先将jar包或apk定义为模块,然后再依赖相应的模块。

对于Android.mk文件,通常是以下两行

LOCAL_PATH := $(call my-dir)  //设置当编译路径为当前文件夹所在路径
include $(CLEAR_VARS)  //清空编译环境的变量(由其他模块设置过的变量)

为了模块编译的方便amdroid源码部分编译,编译系统设置了很多编译环境变量,如下:

对于这个环境变量,编译系统还定义了一些方便的函数,如下:

例子:

  LOCAL_PATH := $(call my-dir)
  include $(CLEAR_VARS)
  # 获取所有子目录中的Java文件
  LOCAL_SRC_FILES := $(call all-subdir-java-files)
  # 当前模块依赖的动态Java库名称
  LOCAL_JAVA_LIBRARIES := com.gityuan.lib
  # 当前模块的名称
  LOCAL_MODULE := demo
  # 将当前模块编译成一个静态的Java库
  include $(BUILD_STATIC_JAVA_LIBRARY)

微信公众号Gityuan | 微博 weibo.com/gityuan | 博客留言区供交流