Android编译原理- source、lunch、make

对于Android研发的同学来说,编译Android系统的过程并不陌生。

首先:source build/envsetup.sh  - 执行build路径下的envsetup.sh脚本。

其次:lunch  - 选择一个特定的编译产品类型。

最后:make  - 执行编译命令,产生编译结果,生成在out/target/product/xxx/下。

相关代码参考使用android-13.0.0_r3版本:http://aospxref.com/android-13.0.0_r3/

更多技术文章,全网首发公众号 “极客钛” 锁定 -上午11点 - ,感谢大家关注、转发、点赞!

一文讲解Android编译原理 (qq.com)

1.source build/envsetup.sh原理 

执行的envsetup.sh,我们只需要看懂这个脚本既可理解。

envsetup.sh这个脚本主要是提供了一些函数和命令,提供给编译使用。其中就包含了我们后面会使用到的lunch和make命令。

http://aospxref.com/android-13.0.0_r3/xref/build/envsetup.sh

第一个命令 - hmm

执行hmm可以看到这个脚本支持的命令,第一行cat <<EOP,意思就是把EOF后面到下一个EOF前面的内容当做一个文件,然后cat 会接收这个文件的内容,而cat默认的输出是标准输出,也就是这个文件的内容会被打印到屏幕上来。

图片

hmm命令函数最后部分的原理,如下。

图片

1.gettop就是获取Android源码的根目录

2.for循环获取根目录下的build/envsetup.sh脚本中所有的function功能,并进行显示。

执行hmm命令最后的结果:

图片

在这里,罗列了一些主要的函数命令用法:

function help()                   # 显示帮助信息function get_abs_build_var()           # 获取绝对变量function get_build_var()             # 获取绝对变量function check_product()             # 检查productfunction check_variant()             # 检查变量function setpaths()                # 设置文件路径function printconfig()              # 打印配置function set_stuff_for_environment()      # 设置环境变量function set_sequence_number()          # 设置序号function settitle()                # 设置标题function choosetype()               # 设置typefunction chooseproduct()              # 设置productfunction choosevariant()              # 设置variantfunction tapas()                  # 功能同choosecombofunction choosecombo()               # 设置编译参数function add_lunch_combo()             # 添加lunch项目function print_lunch_menu()            # 打印lunch列表function lunch()                 # 配置lunchfunction m()                   # make from topfunction findmakefile()             # 查找makefilefunction mm()                   # make from current directoryfunction mmm()                   # make the supplied directoriesfunction croot()                 # 回到根目录function cproj()function pid()function systemstack()function gdbclient()function jgrep()                 # 查找java文件function cgrep()                  # 查找c/cpp文件function resgrep()function tracedmdump()

envsetup.sh脚本最后会执行三个命令:

1.validate_current_shell - 验证当前的shell环境

2.source_vendorsetup - 执行vendorsetup脚本

3.addcompletions -确保bash环境

图片

其中第二步是芯片厂中自行定制化的一步,qcom和mtk等都会使用自家的vendorsetup脚本,我们来看下如何执行vendorsetup脚本。

图片

在获取到Android源码的根目录下,使用shell命令find查找,设定了查找深度为4层目录,4级目录下的是否存在allowed-vendorsetup_sh-files,-n 是判断是否不为空,然后再排序,依次执行。

同理,查找vendorsetup.sh后再依次执行。

一般vendorsetup.sh都在device下的,对应厂商名字的文件夹下,例如mtk平台的Android代码在执行 source build/envsetup.sh时,会引用mtk平台的vendorsetup。

图片

通过基本的流程,可以看出envsetup.sh作用如下:

1.加载了编译时使用到的函数命令,如:help,lunch,m,mm,mmm等。

2.添加了默认编译选项:aosp_arm-eng等系统默认选项(lunch操作在下一个章节介绍)。

3.查找build/<厂商目录>/ 目录下的vendorsetup.sh,如果存在的话,加载执行它,添加厂商自己定义产品的编译选项

图片

其他的函数命令在编译的使用中再对照envsetup.sh脚本的函数进行分析,不会一一介绍。

2.lunch原理 

当执行完souce build/envsetup.sh之后,可以执行lunch进入到菜单进行选择,也可以lunch + 版本名称,直接完成lunch。

例如:

lunch aosp_arm64-eng

lunch函数命令的具体流程:

读取lunch参数,获取用户编译目标到answer变量,如果没有输入参数,调用print_lunch_menu函数显示可选编译项菜单,提示用户继续输入。

图片

在print_lunch_menu中通过COMMON_LUNCH_CHOICES来获取所有的版本名称。

在早期的Android版本(9之前)中是通过add_lunch_combo函数添加进来的。

而新版本的Android(10以后)已经将这个部分弃用,使用COMMON_LUNCH_CHOICES。

图片

根据COMMON_LUNCH_CHOICES的版本名称,引用对应的mk文件。

然后再对输入的数字或者字符进行检查。

图片

  1. grep -q -e "^[0-9][0-9]*$",-q表示quiet模式,也就是不打印信息,-e表示后面跟的是一个用于匹配的模式。这条命令从answer变量中搜寻以两位数字开头的字符串,如果找到,就认为是输入的是数字。然后进一步对这个数字做有没有越界的检查。

2.不是数字的话,尝试匹配这样的字符串 ${variant_and_version%%-*}

这里匹配的是后面跟任意字符,然后必须有个-,最后又不以--结束的字符串。就是期望得到product-varient的形式。

也就是我们之前使用COMMON_LUNCH_CHOICES获取的那些字符串的格式。

比如:aosp_arm-eng,product就是aosp_arm,varient就是eng。

中间的-是必须的。如果发现符合要求的格式的话selection变量就会被$answer赋值,也就是说,selection其实就是一个product-varient模式的字符串。

图片

3.最后将 product赋值给TARGET_PRODUCT ,variant赋值给TARGET_BUILD_VARIANT,做export设置环境变量。

3.make原理 

make命令中会调用get_make_command,最后到soong_ui.bash,以及m,mm,mmm的命令也会调用soong_ui.bash。

图片

从Android10以后,soong_ui.bash替代了make命令,作为编译开始的入口。

在soong_ui.bash中做了三个事,如下:

图片

1.导入microfactory.bash,设置 GOROOT 环境变量,指向 prebuild 的 go 编译工具链,根据参数编译 go 源码生成相应的程序soong_ui。

2.调用 soong_build_go 函数。两个参数的含义,第一参数是编译生成的可执行程序的名字,第二参数是执行程序的源码路径。

3.通过 exec 命令创建进程执行上一步生成的 soong_ui程序,并使用添加的参数。这一步就等同于之前的make命令。

例如,m cameraserver,最终等价于调用 out/soong_ui --make-mode cameraserver,注意这里的 --make-mode 是在 m 函数里引入的

图片

总而言之,build/soong/soong_ui.bash 的最终效果就是帮助我们制作出了一个叫做 soong_ui 的应用程序,放在 out 下。

通过以上的三步,就可以完成Android特定的project的编译。

通过对Android编译源码的分析,有利于我们新建一个自定义的Android project,这对于一个vendor厂商有着重要意义,通过不同的project可以区分不同的产品类型,并且不需要更多的代码仓库。

  • 13
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果你想在 Docker 容器中搭建 Android 编译环境,可以参考以下步骤: 1. 安装 Docker:根据你的操作系统安装 Docker。 2. 获取 Android 源代码:可以参考 Google 官方文档获取 Android 源代码。 3. 创建 Docker 镜像:创建一个 Dockerfile 文件,指定基础镜像、安装必要的软件和配置环境变量等,具体内容可以参考下面的示例。然后使用 docker build 命令构建镜像。 ``` FROM ubuntu:18.04 RUN apt-get update && \ apt-get install -y git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \ lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \ libgl1-mesa-dev libxml2-utils xsltproc unzip ENV PATH=$PATH:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools RUN curl -L https://dl.google.com/android/repository/sdk-tools-linux-4333796.zip -o /tmp/sdk.zip && \ mkdir /opt/android-sdk-linux && \ unzip /tmp/sdk.zip -d /opt/android-sdk-linux && \ rm /tmp/sdk.zip && \ yes | /opt/android-sdk-linux/tools/bin/sdkmanager --licenses && \ /opt/android-sdk-linux/tools/bin/sdkmanager "platform-tools" "build-tools;28.0.3" "platforms;android-28" ``` 4. 运行容器:创建一个容器并挂载你的 Android 源代码目录到容器中,然后进入容器并执行编译命令即可。示例命令如下: ``` docker run -it --rm -v /path/to/android/source:/android-source my-android-build-env /bin/bash cd /android-source source build/envsetup.sh lunch aosp_arm-eng make -j4 ``` 注意,这里的 /path/to/android/source 是你本地的 Android 源代码目录,my-android-build-env 是你刚才构建的 Docker 镜像的名称。另外,编译命令可以根据你的需求进行修改。 希望以上步骤对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客之昂-钛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值