分类 Android 下的文章

转自: http://gityuan.com/2016/03/19/android-build/

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

一、引言

关于Android Build系统,这个话题很早就打算整理下,迟迟没有下笔,决定跟大家分享下。先看下面几条指令,相信编译过Android源码的人都再熟悉不过的。

source setenv.sh
lunch
make -j12

记得最初刚接触Android时,同事告诉我用上面的指令就可以编译Android源码,指令虽短但过几天就记不全或者忘记顺序,每次编译时还需要看看自己的云笔记,冰冷的指令总是难以让我记忆。后来我决定认真研究下这个指令的含义。知其然还需知其所以然,这样能更深层次的理解并记忆,才能与自身的知识体系建立强连接,或许还有意外收获,果然如此,接下来跟大家分享一下在研究上述几条指令含义的过程中,深入了解到的Android Build(编译)系统。

二、编译命令

准备好编译环境后,编译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文件能找到相对应的function,比如上述的命令lunch,make,在文件一定能找到

function lunch(){
    ...
}

function make(){
    ...
}

source envsetup.sh,需要cd到setenv.sh文件所在路径执行,路径可能在build/envsetup.sh,或者integrate/envsetup.sh,再或者不排除有些厂商会封装自己的.sh脚本,但核心思路是一致的。

具体实现这里就不展开说明,下面精炼地总结了一下各个指令用法和功效。

2.1 代码编译

编译指令 解释
m 在源码树的根目录执行编译
mm 编译当前路径下所有模块,但不包含依赖
mmm [module_path] 编译指定路径下所有模块,但不包含依赖
mma 编译当前路径下所有模块,且包含依赖
mmma [module_path] 编译指定路径下所有模块,且包含依赖
make [module_name] 无参数,则表示编译整个Android代码

下面列举部分模块的编译指令:

模块 make命令 mmm命令
init make init mmm system/core/init
zygote make app_process mmm frameworks/base/cmds/app_process
system_server make services mmm frameworks/base/services
java framework make framework mmm frameworks/base
framework资源 make framework-res mmm frameworks/base/core/res
jni framework make libandroid_runtime mmm frameworks/base/core/jni
binder make libbinder mmm frameworks/native/libs/binder

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

Tips:

  • 对于m、mm、mmm、mma、mmma这些命令的实现都是通过make方式来完成的。
  • mmm/mm编译的效率很高,而make/mma/mmma编译较缓慢;
  • make/mma/mmma编译时会把所有的依赖模块一同编译,但mmm/mm不会;
  • 建议:首次编译时采用make/mma/mmma编译;当依赖模块已经编译过的情况,则使用mmm/mm编译。

2.2 代码搜索

搜索指令 解释
cgrep 所有C/C++文件执行搜索操作
jgrep 所有Java文件执行搜索操作
ggrep 所有Gradle文件执行搜索操作
mangrep [keyword] 所有AndroidManifest.xml文件执行搜索操作
mgrep [keyword] 所有Android.mk文件执行搜索操作
sepgrep [keyword] 所有sepolicy文件执行搜索操作
resgrep [keyword] 所有本地res/*.xml文件执行搜索操作
sgrep [keyword] 所有资源文件执行搜索操作

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

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

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

mangrep launcher

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

jgrep zygote

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

sepgrep system_app

Tips: Android源码非常庞大,直接采用grep来搜索代码,不仅方法笨拙、浪费时间,而且搜索出很多无意义的混淆结果。根据具体需求,来选择合适的代码搜索指令,能节省代码搜索时间,提高搜索结果的精准度,方便定位目标代码。

2.3 导航指令

导航指令 解释
croot 切换至Android根目录
cproj 切换至工程的根目录
godir [filename] 跳转到包含某个文件的目录

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

2.4 信息查询

查询指令 解释
hmm 查询所有的指令help信息
findmakefile 查询当前目录所在工程的Android.mk文件路径
print_lunch_menu 查询lunch可选的product
printconfig 查询各项编译变量值
gettop 查询Android源码的根目录
gettargetarch 获取TARGET_ARCH值

2.5 其他指令

上述只是列举比较常用的指令,还有其他指令,而且不同的build编译系统,支持的指令可能会存在一些差异,当忘记这些编译指令,可以通过执行hmm,查询指令的帮助信息。

最后再列举两个比较常用的指令:

  • make clean:执行清理操作,等价于 rm -rf out/
  • make update-api:更新API,在framework API改动后需执行该指令,Api记录在目录frameworks/base/api

三、编译系统

Android 编译系统是Android源码的一部分,用于编译Android系统,Android SDK以及相关文档。该编译系统是由Make文件、Shell以及Python脚本共同组成,其中最为重要的便是Make文件。关于编译系统可参考 理解 Android Build 系统。 www.ibm.com/developerworks/cn/opensource/os-cn-android-build/

3.1 Makefile分类

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

  • 系统核心的Make文件:定义了Build系统的框架,文件全部位于路径/build/core,其他Make文件都是基于该框架编写的;
  • 针对产品的Make文件:定义了具体某个型号手机的Make文件,文件路径位于/device,该目录下往往又以公司名和产品名划分两个子级目录,比如/device/qcom/msm8916
  • 针对模块的Make文件:整个系统分为各个独立的模块,每个模块都一个专门的Make文件,名称统一为”Android.mk”,该文件定义了当前模块的编译方式。Build系统会扫描整个源码树中名为”Android.mk”的问题,并执行相应模块的编译工作。

3.2 编译产物

经过make编译后的产物,都位于/out目录,该目录下主要关注下面几个目录:

  • /out/host:Android开发工具的产物,包含SDK各种工具,比如adb,dex2oat,aapt等。
  • /out/target/common:通用的一些编译产物,包含Java应用代码和Java库;
  • /out/target/product/[product_name]:针对特定设备的编译产物以及平台相关C/C++代码和二进制文件;

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

  • system.img:挂载为根分区,主要包含Android OS的系统文件;
  • ramdisk.img:主要包含init.rc文件和配置文件等;
  • userdata.img:被挂载在/data,主要包含用户以及应用程序相关的数据;

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

3.3 Android.mk解析

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

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

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

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

  • LOCAL_SRC_FILES:当前模块包含的所有源码文件;
  • LOCAL_MODULE:当前模块的名称(具有唯一性);
  • LOCAL_PACKAGE_NAME:当前APK应用的名称(具有唯一性);
  • LOCAL_C_INCLUDES:C/C++所需的头文件路径;
  • LOCAL_STATIC_LIBRARIES:当前模块在静态链接时需要的库名;
  • LOCAL_SHARED_LIBRARIES:当前模块在运行时依赖的动态库名;
  • LOCAL_STATIC_JAVA_LIBRARIES:当前模块依赖的Java静态库;
  • LOCAL_JAVA_LIBRARIES:当前模块依赖的Java共享库;
  • LOCAL_CERTIFICATE:签署当前应用的证书名称,比如platform。
  • LOCAL_MODULE_TAGS:当前模块所包含的标签,可以包含多标签,可能值为debgu,eng,user,development或optional(默认值)

针对这些环境变量,编译系统还定义了一些便捷函数,如下:

  • $(call my-dir):获取当前文件夹路径;
  • $(call all-java-files-under, ):获取指定目录下的所有Java文件;
  • $(call all-c-files-under, ):获取指定目录下的所有C文件;
  • $(call all-Iaidl-files-under, ) :获取指定目录下的所有AIDL文件;
  • $(call all-makefiles-under, ):获取指定目录下的所有Make文件;

示例:

  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)

转自: https://segmentfault.com/a/1190000021742841

基于 Android 9.0。
许多命令时间一长就记不清了,记录一下。

Android 环境引入的命令

在shell中执行"source build/envsetup.sh"后,Android将增加一些命令到当前环境中。

  • lunch:选择编译的产品类型,并存储在当前环境中。
        lunch <product_name>-<build_variant>
  • tapas:与 'lunch' 类似,可以指定编译的应用。
        tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [eng|userdebug|user]
  • printconfig:打印当前配置。
  • croot:切换到顶层目录
  • m:从顶层目录开始编译。
  • mm:编译当前目录中的所有模块,但不包含依赖的模块。

  • mmm:编译指定目录的所有模块,但不包含依赖的模块。可以使用下述方式限制编译的模块。
        mmm dir/:target1,target2.
  • mma:编译当前目录中的所有模块,包含依赖的模块。
  • mmma:编译指定目录的所有模块,包含依赖的模块
  • provision:对设备进行固件升级,选项将被传递到 fastboot 中。
  • cgrep:在当前目录的所有 C/C++ 文件中查找。
  • ggrep:在当前目录的所有 Gradle 文件中查找。
  • jgrep:在当前目录的所有 Java 文件中查找。
  • resgrep:在当前目录的所有 res/*.xml 文件中查找。
  • mangrep:在当前目录的所有 AndroidManifest.xml 文件中查找。
  • mgrep:在当前目录的所有 Makefiles 文件中查找。
  • sepgrep:在当前目录的所有 sepolicy 文件中查找。
  • sgrep:在当前目录的所有文件中查找。
  • godir:切换到包含指定文件的目录。

make相关命令

make 或 m 后面可以跟随不同的参数来指定编译目标。

  • droid:默认的 make 编译目标。
  • all:编译所有内容,包括不含droid标记的内容。编译服务器会运行此命令,以确保项目中包含Android.mk文件的所有元素都会编译。
  • checkbuild:编译所有的模块。
  • showcommands:显示编译步骤中实际的编译指令。
  • PRODUCT-xxx-yyy:编译指定的产品。
  • dump-products:显示产品的编译信息。

  • LOCAL_MODULE:编译指定的模块。例如,
        make runtime
  • nothing:不编译任何事情,只是解析和验证编译框架。
  • java:编译项目中的所有java代码。
  • native:编译项目中的所有native代码。
  • host:编译host端代码。
  • target:编译target端代码。
  • (java|native)-(host|target):按组合编译限定代码。
  • (host|target)-(java|native):按组合编译限定代码。
  • snod:快速重新编译system镜像。
  • vnod:快速重新编译vendor镜像。
  • pnod:快速重新编译product镜像。
  • update-api:更新SDK API。
  • otapackage:生成OTA升级包。
  • updatepackage:生成zip升级包。
  • docs:编译文档。
  • ndk-docs:生成ndk文档。
  • sdk:编译生成SDK。
  • ndk:编译生成NDK。
  • ramdisk:编译生成ramdisk。
  • systemtarball:生成system的tar包。
  • boottarball:生成boot的tar包。
  • userdatatarball:生成data的tar包。
  • systemimage:生成system.img镜像。
  • bootimage:生成boot.img镜像。
  • vbmetaimage:生成vbmeta.img镜像。
  • userdateimage:生成userdata.img镜像。
  • cacheimage:生成cache.img镜像。
  • bptimage:生成partition-table.img镜像。
  • vendorimage:生成vendor.img镜像。
  • productimage:生成product.img镜像。
  • apps_only:编译不包含 user,userdebug,eng 标签的应用程序。
  • dist:拷贝输出到dist目录。
  • dist_files:仅仅拷贝库文件到dist目录。
  • libandroid_runtime:编译JNI相关内容。
  • framework:编译java framework相关内容。
  • services:编译系统服务相关内容。
  • cts:编译CTS测试套件。
  • vts:编译VTS测试套件。

make clean 相关命令

  • clean:清除当前配置编译的所有文件,等同于rm -rf out//。
  • **clean-$(LOCAL_MODULE):清理指定模块的编译结果。
  • clean-$(LOCAL_PACKAGE_NAME):清理指定包的编译结果。
  • clobber:清除所有输出,等同于rm -rf out/。
  • dataclean:删除当前配置上data目录的所有文件。
  • clean-sdk:清理SDK编译输出。
  • installclean:清除与编译类型相关的文件。在切换编译目标是使用该命令可以加快编译。

new product

new directory

device/[company]/[device] [device] is your PCBA name. product is your software.

mkdir -p device/qiushao/pure

lunch
--> COMMON_LUNCH_CHOICES := pure-eng(AndroidProducts.mk)
--> PRODUCT_MAKEFILES := $(LOCAL_DIR)/pure.mk(AndroidProducts.mk)
--> PRODUCT_DEVICE := pure(pure.mk)
--> device/[company]/pure/BoardConfig.mk
==> out directory: PRODUCT_NAME := pure(pure.mk)

vim AndroidProducts.mk

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/pure.mk

COMMON_LUNCH_CHOICES := \
    pure-eng
vim pure.mk

$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.mk)

PRODUCT_NAME   := pure
PRODUCT_DEVICE := pure
vim BoardConfig.mk

include $(SRC_TARGET_DIR)/board/generic_x86_64/BoardConfig.mk
tree 

.
└── pure
    ├── AndroidProducts.mk
    ├── BoardConfig.mk
    └── pure.mk

pre

sudo apt-get install -y openjdk-8-jdk
sudo 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 libgl1-mesa-dev libxml2-utils xsltproc unzip

download

git

sudo apt install git
git config --global user.name "xyz"
git config --global user.email "xyz@gmail.com"

ethstatus

sudo apt install -y ethstatus net-tools

use ifconfig to get your net name, may be it looks like wlp4s0, then use ethstatus -i wlp4s0 to get net status.

repo

mkdir ~/bin
curl https://mirrors.tuna.tsinghua.edu.cn/git/git-repo -o ~/bin/repo
chmod +x ~/bin/repo
mkdir -p ~/source/android-10
vim ~/repo_sync.sh

#!/bin/bash

export PATH=$PATH:~/bin 
export REPO_URL="https://mirrors.tuna.tsinghua.edu.cn/git/git-repo/"

cd ~/source/android-10
repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-10.0.0_r8
repo sync

compile

vim build_aosp.sh
#!/bin/bash

cd source/android-10/
source build/envsetup.sh
lunch aosp_x86_64-eng

#make system-api-stubs-docs-update-current-api

if error with 1 or 137, the ram may be less than needed, you should increase swap size or ram size.

emulator

vim emulator.sh

#!/bin/bash

cd source/android-10/

source build/envsetup.sh
lunch aosp_x86_64-eng

#sudo emulator
emulator

if error is "Please ensure KVM is properly installed and usable." you need:

  1. sudo apt install -y qemu-kvm cpu-checker
  2. use kvm-ok to check the kvm has already?
  3. use usermod -a -G kvm xyz to add user: xyz in kvm group.
  4. user echo 'KERNEL=="kvm",GROUP="kvm",MODE="0660"' >> /etc/udev/rules.d/androidUseKVM.rules to add kvm rules.
  5. reboot or relogin

if still has the error like "grant current user access to /dev/kvm", "/dev/kvm devices: permission denies", then sudo chown xyz -R /dev/kvm

reference:

Ubuntu 18.04 emulator运行Android源码编译的 X86 虚拟机image
https://blog.csdn.net/csusunxgg/article/details/81060890
Ubentu编译Android源码(AOSP)
https://www.cnblogs.com/caoxinyu/p/10568480.html

转自: https://blog.csdn.net/u011913612/article/details/52503318

Android编译系统分析系列文章: android编译系统分析(一)-source build/envsetup.sh与lunch Android编译系统(二)-mm编译单个模块 android编译系统分析(三)-make android编译系统(四)-实战:新增一个产品 Android编译系统分析(五)-system.img的生成过程

我们在完整编译android系统的时候,最终会生成几个重要的镜像文件,其中有system.img,userdata.img,ramdisk.img等。这篇文章的目的是分析system.img的生成过程。 回想下我们完整编译android系统时的动作,我们会在android源码顶级目录执行make命令,这样就会完整的编译android系统,我们没有传入任何参数(-jx等加快编译的除外),因为我们没有明确指定make的目标,所以android编译系统会执行默认的编译目标,也就是droid。因此,我们还是从droid着手,看看system.img怎么生成。

- 阅读剩余部分 -

转自: https://blog.csdn.net/u011913612/article/details/52434445

Android编译系统分析系列文章:

android编译系统分析一<source build/envsetup.sh与lunch> Android编译系统<二>-mm编译单个模块 android编译系统分析(三)-make android编译系统(四)-实战:新增一个产品 Android编译系统分析(五)-system.img的生成过程

通过上一节“android编译系统(三)-make”的分析,初步理清楚了编译初期加载产品相关信息的流程,整个过程主要涉及三个文件:1.AndroidProducts.mk,2.具体产品的配置文件,3.BoardConfig.mk,加上lunch需要的vendorsetup.sh文件,总共只需要四个文件就可以了,所以我们不妨成热打铁,赶紧尝试下如何新增一个产品。因此,android编译系统镜像文件的创建过程方到下一节。

- 阅读剩余部分 -

转自: https://blog.csdn.net/u011913612/article/details/52434411

Android编译系统分析系列文章:

android编译系统分析一<source build/envsetup.sh与lunch> Android编译系统<二>-mm编译单个模块 android编译系统分析(三)-make android编译系统(四)-实战:新增一个产品 Android编译系统分析(五)-system.img的生成过程

这篇博客的目标是摸清楚默认编译整个android系统时代码的流程。

当我们执行make的时候,会查找当前的Makefie文件或者makefile文件并且执行,在android顶级源码目录下面,确实有个Makefile,它之后一行内容:

### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###

因此,正真执行的是build/core/main.mk

- 阅读剩余部分 -

转自: https://blog.csdn.net/u011913612/article/details/52415948

Android编译系统分析系列文章:

android编译系统分析一<source build/envsetup.sh与lunch> Android编译系统<二>-mm编译单个模块 android编译系统分析(三)-make android编译系统(四)-实战:新增一个产品 Android编译系统分析(五)-system.img的生成过程

因为Android的编译系统不同于Linux Kernel的递归式的编译系统,它的编译系统是一种称之为independent的模式,每个模块基本独立(它有可能依赖其他模块),每个模块都可以单独编译,这是Android independent编译系统模式的好处。但这并不意味着它是完美的,普通电脑编译android系统需要8个小时甚至更多(以本人的电脑为例),而编译linux kernel只需要半个小时,代码量是一回事,由independent模式造成的编译时间长应该是可以肯定的。正因为每个模块可以单独编译,所以android系统的编译就是依次编译每个模块,然后把所有编译好的模块和其他一些文件一起打包成镜像文件。因此,只要理解了每个模块的编译,理解android系统的编译就轻松多了。(以上均是个人观点,欢迎拍砖)

- 阅读剩余部分 -

出现这个报错,是因为子文件夹下面也有 .git,有两种方法解决:

  • 直接删除子文件夹的 .git,如果使用 find . -name ".git" 发现要删除的比较少,就手动删除,如果要删除的比较多,就使用 find . -name ".git" | xargs rm -Rf 批量删除。
  • 把子文件夹作为模块来进行管理,这个比较麻烦,如果是大型多人合作工程,可以考虑使用 repo 这样专门的管理模式。如果是小团队,就不如第一种加上复制粘贴来的快捷。

参考

fatal: 'git status --porcelain'
https://blog.csdn.net/qq_40028324/article/details/82770466
删除文件夹下所有的.git文件
https://blog.csdn.net/wuyanyanstrong/article/details/52766293
git submodule 的使用
https://www.jianshu.com/p/e27a978ddb88
https://blog.justwe.site/post/git-submodule/

本文是参考 http://www.ramlife.org/2021/09/08/407.html 在 android 10 源码上面对 envsetup.sh 进行初步分析。

envsetup.sh

envsetup.sh 链接位置在 build/envsetup.sh,真实位置是 build/make/envsetup.sh。 在脚本中,能够看到有很多函数,最下面直接调用的只有三个函数:

validate_current_shell
source_vendorsetup
addcompletions

validate_current_shell

validate_current_shell 中功能很简单,函数名称也能够看出来,检测当前的 shell 是哪种,通过 local current_sh="$(ps -o command -p $$)" 获取当前的 bash 程序,我使用的是 bash,所以这个变量获取到的是 COMMAND -bash , 所以执行 function check_type() { type -t "$1"; }.

type 命令属于 bash 内建命令,-t选项显示参数指定类型信息。会打印字符串:alias, keyword, function, builtin, or file

# type -t gcc
file
#type -t cd
builtin
 #type -t ll
alias

# type -t if
keyword
#type -t print

参考: bash内建命令type简介
https://blog.csdn.net/hanzhen1135/article/details/48340097

source_vendorsetup

看函数名称,应该是执行厂商的配置。

    allowed=
    for f in $(find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
        if [ -n "$allowed" ]; then
            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
            echo "  $allowed"
            echo "  $f"
            return
        fi
        allowed="$f"
    done

上面在 device, vendor, product 三个文件夹中,向下找 4层路径,找名字是 'allowed-vendorsetup_sh-files' 的文件, -L 表示是链接的时候,去源文件那边去找,而不是链接本身。我们实际运行的时候,allowed 为空。

参考: Linux基础:文件查找find命令详细讲解
http://www.manongjc.com/article/19084.html

    allowed_files=
    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
    for dir in device vendor product; do
        for f in $(test -d $dir && \
            find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do

            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
                echo "including $f"; . "$f"
            else
                echo "ignoring $f, not in $allowed"
            fi
        done
    done

上面这段代码是在 device, vendor, product 三个文件夹下面,找四层,找 'vendorsetup.sh',找到之后,先判断 allowed 是零,或者 allowed_files 符合 $f 这个正则的模型,然后就会 include进去,在运行 . $f 意思是再 source $f。 最终输出就是:

including vendor/qcom/opensource/core-utils/vendorsetup.sh
including vendor/qcom/proprietary/common/vendorsetup.sh
including vendor/qcom/proprietary/prebuilt_HY11/vendorsetup.sh
*****Could not create symlink*******
sdk/current/androidx-README.md::frameworks/support/README.md
vendor/qcom/opensource/core-utils/build.sh::build.sh
****************END******************
Created 85 symlinks out of 87 mapped links..
vendor/qcom/opensource/core-utils/vendorsetup.sh

这个脚本里面只有一句: export QTI_BUILDTOOLS_DIR=$(dirname ${BASH_SOURCE[0]}) BASH_SOURCE[0] 等价于 BASH_SOURCE ,取得当前执行的 shell 文件所在的路径及文件名。dirname 去除文件名中的非目录部分,仅显示与目录有关的部分。 所以这句的意思是 QTI_BUILDTOOLS_DIR 这个值就是 vendorsetup.sh 当前目录的值了。

参考: Shell中的BASH_SOURCE
https://blog.csdn.net/lizhiqiang1217/article/details/94737535

vendor/qcom/proprietary/common/vendorsetup.sh

这个脚本里面是:

export QCPATH="$(pwd)/vendor/qcom/proprietary"
export QCPATH_COMMONSYS="${QCPATH}/commonsys"
export SDCLANG_AE_CONFIG="${QCPATH}/common-noship/etc/sdclang.json"
export SDCLANG_CONFIG="${QCPATH}/common/config/sdclang.json"
export SDCLANG_CONFIG_AOSP="${QCPATH}/common/config/sdclang-pureAOSP.json"
if [ -f "${QCPATH}/qrsp/mpgen/mpgen.py" ]; then
export RTIC_MPGEN="python ${QCPATH}/qrsp/mpgen/mpgen.py"
fi

对这些变量进行赋值,并 export 出来。

vendor/qcom/proprietary/prebuilt_HY11/vendorsetup.sh

脚本内容:

links_dir="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))"
links_path="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))/links"
sys_links_path="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))/system_links"
ven_links_path="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))/vendor_links"
failed_links=""
count=0
if [[ -f "$links_path" || -f "$sys_links_path" || -f "$ven_links_path" ]];then
  total_links=$(cat $links_dir/*links| wc -l)
  for i in $(cat $links_dir/*links);do
    src=$(echo $i | awk -F:: '{print $1}')
    dest=$(echo $i | awk -F:: '{print $2}')
    if [ -e "$dest" ];then
      rm -rf $dest
    fi
    if [[ -e $src && ! -e $dest ]];then
      mkdir -p $(dirname $dest)
      ln -srf $src $dest
      count=$(($count + 1))
    else
      failed_links="$failed_links $i"
    fi
  done
  if [ ! -z "$failed_links" ];then
    echo "*****Could not create symlink*******"
    echo $failed_links | sed 's/[[:space:]]/\n/g'
    echo "****************END******************"
  fi
  echo "Created $count symlinks out of $total_links mapped links.."
fi

readlink 用于得出链接的真实路径,-e 是递归的读取. 就是为了获得真正的 vendorsetup.h 所在的文件夹。 cat $links_dir/*links | wc -l 指的是统计 links_dir文件夹下所有的 *links,看里面有多少个换行符,也就是有多少行。 然后就是简单的把源文件通过软连接链接到目的路径。ln -srf 意思是如果目的地有软连接就强制删除,并且这个软连接是相对位置的软连接,而不是绝对位置的软连接。

把这个文件中链接部分增加了打印信息,结果如下:

total links:  87
build/make/CleanSpec.mk::build/CleanSpec.mk
---> src:  build/make/CleanSpec.mk
<--- dest:  build/CleanSpec.mk
======
build/make/buildspec.mk.default::build/buildspec.mk.default
---> src:  build/make/buildspec.mk.default
<--- dest:  build/buildspec.mk.default
======
build/make/core::build/core
---> src:  build/make/core
<--- dest:  build/core
======
build/make/envsetup.sh::build/envsetup.sh
---> src:  build/make/envsetup.sh
<--- dest:  build/envsetup.sh
======
build/make/target::build/target
---> src:  build/make/target
<--- dest:  build/target
======
build/make/tools::build/tools
---> src:  build/make/tools
<--- dest:  build/tools
======
build/soong/root.bp::Android.bp
---> src:  build/soong/root.bp
<--- dest:  Android.bp
======
build/soong/bootstrap.bash::bootstrap.bash
---> src:  build/soong/bootstrap.bash
<--- dest:  bootstrap.bash
======
sdk/current/androidx-README.md::frameworks/support/README.md
---> src:  sdk/current/androidx-README.md
<--- dest:  frameworks/support/README.md
======
vendor/codeaurora/commonsys/packages/apps/SoundRecorder/app_qtiSoundRecorder_system_product.mk::vendor/qcom/defs/product-defs/system/app_qtiSoundRecorder_product.mk
---> src:  vendor/codeaurora/commonsys/packages/apps/SoundRecorder/app_qtiSoundRecorder_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_qtiSoundRecorder_product.mk
======
vendor/qcom/proprietary/qdssagent/qdssagent-ship-vendor-product.mk::vendor/qcom/defs/product-defs/legacy/qdssagent-ship-vendor-product.mk
---> src:  vendor/qcom/proprietary/qdssagent/qdssagent-ship-vendor-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/qdssagent-ship-vendor-product.mk
======
device/qcom/common/generate_extra_images.mk::vendor/qcom/build/tasks/generate_extra_images.mk
---> src:  device/qcom/common/generate_extra_images.mk
<--- dest:  vendor/qcom/build/tasks/generate_extra_images.mk
======
device/qcom/common/stop_scan.mk::kernel/Android.mk
---> src:  device/qcom/common/stop_scan.mk
<--- dest:  kernel/Android.mk
======
device/qcom/common/stop_scan.mk::disregard/Android.mk
---> src:  device/qcom/common/stop_scan.mk
<--- dest:  disregard/Android.mk
======
vendor/codeaurora/commonsys/packages/apps/Mms/app_mms_system_product.mk::vendor/qcom/defs/product-defs/system/app_mms_product.mk
---> src:  vendor/codeaurora/commonsys/packages/apps/Mms/app_mms_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_mms_product.mk
======
vendor/codeaurora/commonsys/packages/apps/SnapdragonMusic/app_snapMusic_system_product.mk::vendor/qcom/defs/product-defs/system/app_snapMusic_product.mk
---> src:  vendor/codeaurora/commonsys/packages/apps/SnapdragonMusic/app_snapMusic_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_snapMusic_product.mk
======
vendor/qcom/proprietary/commonsys/qrdplus/sva/app_sva_system_product.mk::vendor/qcom/defs/product-defs/system/app_sva_product.mk
---> src:  vendor/qcom/proprietary/commonsys/qrdplus/sva/app_sva_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_sva_product.mk
======
vendor/qcom/proprietary/commonsys/qrdplus/Extension/app_extension_system_product.mk::vendor/qcom/defs/product-defs/system/app_extension_product.mk
---> src:  vendor/qcom/proprietary/commonsys/qrdplus/Extension/app_extension_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_extension_product.mk
======
hardware/qcom/gps/gps_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/gps-product-hal.mk
---> src:  hardware/qcom/gps/gps_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/gps-product-hal.mk
======
hardware/qcom/gps/gps_vendor_board.mk::vendor/qcom/defs/board-defs/vendor/gps-board.mk
---> src:  hardware/qcom/gps/gps_vendor_board.mk
<--- dest:  vendor/qcom/defs/board-defs/vendor/gps-board.mk
======
vendor/qcom/opensource/location/gps_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/gps-product-opensource.mk
---> src:  vendor/qcom/opensource/location/gps_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/gps-product-opensource.mk
======
vendor/qcom/opensource/data-ipa-cfg-mgr/ipacm_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/ipacm_vendor_product.mk
---> src:  vendor/qcom/opensource/data-ipa-cfg-mgr/ipacm_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/ipacm_vendor_product.mk
======
vendor/qcom/proprietary/cne/shipcne_vendor_product.mk::vendor/qcom/defs/product-defs/legacy/shipcne_vendor_product.mk
---> src:  vendor/qcom/proprietary/cne/shipcne_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/shipcne_vendor_product.mk
======
vendor/qcom/proprietary/cne/cne_vendor_product_noship.mk::vendor/qcom/defs/product-defs/legacy/cne_vendor_product_noship.mk
---> src:  vendor/qcom/proprietary/cne/cne_vendor_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cne_vendor_product_noship.mk
======
vendor/qcom/proprietary/cne/cne_vendor_board_noship.mk::vendor/qcom/defs/board-defs/legacy/cne_vendor_board_noship.mk
---> src:  vendor/qcom/proprietary/cne/cne_vendor_board_noship.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/cne_vendor_board_noship.mk
======
vendor/qcom/proprietary/cne/cne_wqe_vendor_product_noship.mk::vendor/qcom/defs/product-defs/legacy/cne_wqe_vendor_product_noship.mk
---> src:  vendor/qcom/proprietary/cne/cne_wqe_vendor_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cne_wqe_vendor_product_noship.mk
======
vendor/qcom/proprietary/cne/cne-test_vendor_product.mk::vendor/qcom/defs/product-defs/legacy/cne-test_vendor_product.mk
---> src:  vendor/qcom/proprietary/cne/cne-test_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cne-test_vendor_product.mk
======
vendor/qcom/proprietary/data/data_prop_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/data_prop_vendor_product.mk
---> src:  vendor/qcom/proprietary/data/data_prop_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/data_prop_vendor_product.mk
======
vendor/qcom/proprietary/qmi/qmi_data_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/qmi_data_vendor_product.mk
---> src:  vendor/qcom/proprietary/qmi/qmi_data_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/qmi_data_vendor_product.mk
======
vendor/qcom/proprietary/qcril-data-hal/datamodule/module/qcril-data-product.mk::vendor/qcom/defs/product-defs/legacy/qcril-data-product.mk
---> src:  vendor/qcom/proprietary/qcril-data-hal/datamodule/module/qcril-data-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/qcril-data-product.mk
======
vendor/qcom/proprietary/nqnfc-firmware/nfc_proprietary_product.mk::vendor/qcom/defs/product-defs/legacy/nfc-proprietary-product.mk
---> src:  vendor/qcom/proprietary/nqnfc-firmware/nfc_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/nfc-proprietary-product.mk
======
vendor/nxp/opensource/commonsys/packages/apps/Nfc/nfc_system_product.mk::vendor/qcom/defs/product-defs/legacy/nfc-system-product.mk
---> src:  vendor/nxp/opensource/commonsys/packages/apps/Nfc/nfc_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/nfc-system-product.mk
======
vendor/nxp/opensource/halimpl/nfc_vendor_product.mk::vendor/qcom/defs/product-defs/legacy/nfc-vendor-product.mk
---> src:  vendor/nxp/opensource/halimpl/nfc_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/nfc-vendor-product.mk
======
vendor/qcom/proprietary/ims-ship/ims_vendor_product_noship.mk::vendor/qcom/defs/product-defs/legacy/ims_vendor_product_noship.mk
---> src:  vendor/qcom/proprietary/ims-ship/ims_vendor_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/ims_vendor_product_noship.mk
======
vendor/qcom/proprietary/commonsys-intf/adsprpc_ship/adsprpc_system_product.mk::vendor/qcom/defs/product-defs/system/adsprpc_system_product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/adsprpc_ship/adsprpc_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/adsprpc_system_product.mk
======
vendor/qcom/proprietary/commonsys-intf/adsprpc_ship/adsprpc_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/adsprpc_vendor_product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/adsprpc_ship/adsprpc_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/adsprpc_vendor_product.mk
======
vendor/qcom/proprietary/dspservices_ship/contexthub_system_product.mk::vendor/qcom/defs/product-defs/system/contexthub_system_product.mk
---> src:  vendor/qcom/proprietary/dspservices_ship/contexthub_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/contexthub_system_product.mk
======
vendor/qcom/proprietary/dspservices_ship/chre_system_product.mk::vendor/qcom/defs/product-defs/vendor/chre_system_product.mk
---> src:  vendor/qcom/proprietary/dspservices_ship/chre_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/chre_system_product.mk
======
vendor/qcom/proprietary/dspservices_ship/remote_debug_agent_vendor_board.mk::vendor/qcom/defs/board-defs/vendor/remote_debug_agent_vendor_board.mk
---> src:  vendor/qcom/proprietary/dspservices_ship/remote_debug_agent_vendor_board.mk
<--- dest:  vendor/qcom/defs/board-defs/vendor/remote_debug_agent_vendor_board.mk
======
vendor/qcom/proprietary/cv/fastcv/cv_vendor_product.mk::vendor/qcom/defs/product-defs/legacy/cv_vendor_product.mk
---> src:  vendor/qcom/proprietary/cv/fastcv/cv_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cv_vendor_product.mk
======
vendor/qcom/proprietary/cv/fastcv/cv_vendor_board.mk::vendor/qcom/defs/board-defs/legacy/cv_vendor_board.mk
---> src:  vendor/qcom/proprietary/cv/fastcv/cv_vendor_board.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/cv_vendor_board.mk
======
vendor/qcom/proprietary/cv/fastcv/cv_system_product.mk::vendor/qcom/defs/product-defs/legacy/cv_system_product.mk
---> src:  vendor/qcom/proprietary/cv/fastcv/cv_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cv_system_product.mk
======
vendor/qcom/proprietary/securemsm/config/smcinvoke_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/smcinvoke_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/smcinvoke_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/smcinvoke_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/qseecomd_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/qseecomd_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/qseecomd_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/qseecomd_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/cpz_vendor_proprietary_board.mk::vendor/qcom/defs/board-defs/vendor/cpz_vendor_proprietary_board.mk
---> src:  vendor/qcom/proprietary/securemsm/config/cpz_vendor_proprietary_board.mk
<--- dest:  vendor/qcom/defs/board-defs/vendor/cpz_vendor_proprietary_board.mk
======
vendor/qcom/proprietary/securemsm/config/cpz_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/cpz_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/cpz_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/cpz_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/keymaster_vendor_proprietary_board.mk::vendor/qcom/defs/board-defs/vendor/keymaster_vendor_proprietary_board.mk
---> src:  vendor/qcom/proprietary/securemsm/config/keymaster_vendor_proprietary_board.mk
<--- dest:  vendor/qcom/defs/board-defs/vendor/keymaster_vendor_proprietary_board.mk
======
vendor/qcom/proprietary/securemsm/config/keymaster_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/keymaster_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/keymaster_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/keymaster_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/gp_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/gp_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/gp_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/gp_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/tloc_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/tloc_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/tloc_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/tloc_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/securemsm/config/qseecom_hal_vendor_proprietary_product.mk::vendor/qcom/defs/product-defs/vendor/qseecom_hal_vendor_proprietary_product.mk
---> src:  vendor/qcom/proprietary/securemsm/config/qseecom_hal_vendor_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/qseecom_hal_vendor_proprietary_product.mk
======
vendor/qcom/proprietary/commonsys/securemsm/securemsm_system_product.mk::vendor/qcom/defs/product-defs/system/securemsm_product.mk
---> src:  vendor/qcom/proprietary/commonsys/securemsm/securemsm_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/securemsm_product.mk
======
vendor/qcom/proprietary/commonsys/securemsm/config/gp_system_proprietary_product.mk::vendor/qcom/defs/product-defs/system/gp_system_proprietary_product.mk
---> src:  vendor/qcom/proprietary/commonsys/securemsm/config/gp_system_proprietary_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/gp_system_proprietary_product.mk
======
vendor/qcom/proprietary/commonsys/securemsm/config/qseecom_lib_system_product.mk::vendor/qcom/defs/product-defs/system/qseecom_lib_system_product.mk
---> src:  vendor/qcom/proprietary/commonsys/securemsm/config/qseecom_lib_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/qseecom_lib_system_product.mk
======
vendor/qcom/proprietary/gps-release/gps_system_product.mk::vendor/qcom/defs/product-defs/system/gps-product.mk
---> src:  vendor/qcom/proprietary/gps-release/gps_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/gps-product.mk
======
vendor/qcom/proprietary/gps-release/gps_system_board.mk::vendor/qcom/defs/board-defs/system/gps-board.mk
---> src:  vendor/qcom/proprietary/gps-release/gps_system_board.mk
<--- dest:  vendor/qcom/defs/board-defs/system/gps-board.mk
======
vendor/qcom/proprietary/gps-release/gps_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/gps-product.mk
---> src:  vendor/qcom/proprietary/gps-release/gps_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/gps-product.mk
======
vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-vendor-proprietary-board.mk::vendor/qcom/defs/board-defs/legacy/bt-vendor-proprietary-board.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-vendor-proprietary-board.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/bt-vendor-proprietary-board.mk
======
vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-vendor-proprietary-product.mk::vendor/qcom/defs/product-defs/legacy/bt-vendor-proprietary-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-vendor-proprietary-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/bt-vendor-proprietary-product.mk
======
vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-system-proprietary-product.mk::vendor/qcom/defs/product-defs/legacy/bt-system-proprietary-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/bluetooth/bt-system-proprietary-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/bt-system-proprietary-product.mk
======
vendor/qcom/opensource/commonsys-intf/bluetooth/bt-commonsys-intf-legacy-board.mk::vendor/qcom/defs/board-defs/legacy/bt-commonsys-intf-legacy-board.mk
---> src:  vendor/qcom/opensource/commonsys-intf/bluetooth/bt-commonsys-intf-legacy-board.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/bt-commonsys-intf-legacy-board.mk
======
vendor/qcom/opensource/commonsys-intf/bluetooth/bt-system-opensource-product.mk::vendor/qcom/defs/product-defs/legacy/bt-system-opensource-product.mk
---> src:  vendor/qcom/opensource/commonsys-intf/bluetooth/bt-system-opensource-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/bt-system-opensource-product.mk
======
vendor/qcom/proprietary/commonsys/voiceui/app_voiceui_system_product.mk::vendor/qcom/defs/product-defs/system/app_voiceui_product.mk
---> src:  vendor/qcom/proprietary/commonsys/voiceui/app_voiceui_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/app_voiceui_product.mk
======
vendor/qcom/opensource/core-utils/build/QSSI_violators.mk::vendor/qcom/build/tasks/QSSI_violators.mk
---> src:  vendor/qcom/opensource/core-utils/build/QSSI_violators.mk
<--- dest:  vendor/qcom/build/tasks/QSSI_violators.mk
======
vendor/qcom/opensource/core-utils/build.sh::build.sh
---> src:  vendor/qcom/opensource/core-utils/build.sh
<--- dest:  build.sh
======
vendor/qcom/proprietary/qrdplus/PowerOffAlarm/app_poweroffalarm_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/app_poweroffalarm_product.mk
---> src:  vendor/qcom/proprietary/qrdplus/PowerOffAlarm/app_poweroffalarm_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/app_poweroffalarm_product.mk
======
vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/telephony-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/telephony-product.mk
======
vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-noship_system_product.mk::vendor/qcom/defs/product-defs/system/telephony-noship-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-noship_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/telephony-noship-product.mk
======
vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony_system_product.mk::vendor/qcom/defs/product-defs/system/telephony-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/telephony-product.mk
======
vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-intf_system_product.mk::vendor/qcom/defs/product-defs/system/telephony-intf-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-intf_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/system/telephony-intf-product.mk
======
vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-intf_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/telephony-intf-product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/telephony/build/telephony-intf_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/telephony-intf-product.mk
======
vendor/qcom/proprietary/commonsys/cne/cne_commonsys_system_product.mk::vendor/qcom/defs/product-defs/legacy/cne_commonsys_system_product.mk
---> src:  vendor/qcom/proprietary/commonsys/cne/cne_commonsys_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cne_commonsys_system_product.mk
======
vendor/qcom/proprietary/commonsys/cne/cne_system_product_noship.mk::vendor/qcom/defs/product-defs/legacy/cne_system_product_noship.mk
---> src:  vendor/qcom/proprietary/commonsys/cne/cne_system_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/cne_system_product_noship.mk
======
vendor/qcom/proprietary/commonsys/ims-ship/ims_commonsys_system_product.mk::vendor/qcom/defs/product-defs/legacy/ims_commonsys_system_product.mk
---> src:  vendor/qcom/proprietary/commonsys/ims-ship/ims_commonsys_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/ims_commonsys_system_product.mk
======
vendor/qcom/proprietary/commonsys/ims-ship/ims-internal_system_product_noship.mk::vendor/qcom/defs/product-defs/legacy/ims-internal_system_product_noship.mk
---> src:  vendor/qcom/proprietary/commonsys/ims-ship/ims-internal_system_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/ims-internal_system_product_noship.mk
======
vendor/qcom/proprietary/commonsys/ims-ship/ims_system_product_noship.mk::vendor/qcom/defs/product-defs/legacy/ims_system_product_noship.mk
---> src:  vendor/qcom/proprietary/commonsys/ims-ship/ims_system_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/ims_system_product_noship.mk
======
vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_board.mk::vendor/qcom/defs/board-defs/legacy/data_commonsys-intf_board.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_board.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/data_commonsys-intf_board.mk
======
vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_vendor_product.mk::vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_vendor_product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_vendor_product.mk
======
vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_system_product.mk::vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_system_product.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_system_product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_system_product.mk
======
vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_system_product_noship.mk::vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_system_product_noship.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_system_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_system_product_noship.mk
======
vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_vendor_product_noship.mk::vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_vendor_product_noship.mk
---> src:  vendor/qcom/proprietary/commonsys-intf/data/data_commonsys-intf_vendor_product_noship.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/data_commonsys-intf_vendor_product_noship.mk
======
vendor/qcom/proprietary/mm-camera/mm-camera2/configs/camera_vendor_product.mk::vendor/qcom/defs/product-defs/vendor/camera_vendor_product.mk
---> src:  vendor/qcom/proprietary/mm-camera/mm-camera2/configs/camera_vendor_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/camera_vendor_product.mk
======
vendor/qcom/proprietary/vpp/config/vpp-vendor-board.mk::vendor/qcom/defs/board-defs/legacy/vpp-board.mk
---> src:  vendor/qcom/proprietary/vpp/config/vpp-vendor-board.mk
<--- dest:  vendor/qcom/defs/board-defs/legacy/vpp-board.mk
======
vendor/qcom/proprietary/vpp/config/vpp-vendor-product.mk::vendor/qcom/defs/product-defs/legacy/vpp-product.mk
---> src:  vendor/qcom/proprietary/vpp/config/vpp-vendor-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/vpp-product.mk
======
vendor/qcom/proprietary/configstore/configstore-product.mk::vendor/qcom/defs/product-defs/legacy/configstore-product.mk
---> src:  vendor/qcom/proprietary/configstore/configstore-product.mk
<--- dest:  vendor/qcom/defs/product-defs/legacy/configstore-product.mk
======
vendor/qcom/proprietary/coretech-config-vendor/thermal-engine/thermal-engine_product.mk::vendor/qcom/defs/product-defs/vendor/thermal-engine_product.mk
---> src:  vendor/qcom/proprietary/coretech-config-vendor/thermal-engine/thermal-engine_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/thermal-engine_product.mk
======
vendor/qcom/proprietary/coretech-config-vendor/thermal-hal/thermal-hal_product.mk::vendor/qcom/defs/product-defs/vendor/thermal-hal_product.mk
---> src:  vendor/qcom/proprietary/coretech-config-vendor/thermal-hal/thermal-hal_product.mk
<--- dest:  vendor/qcom/defs/product-defs/vendor/thermal-hal_product.mk
======

参考: linux shell readlink 获取当前脚本文件绝对路径
https://www.it610.com/article/1304474769474752512.htm
linux shell 指令 诸如-d, -f, -e之类的判断表达式简介
https://www.cnblogs.com/zrmw/p/9625727.html
shell 命令之 wc -l
https://www.cnblogs.com/drjava/p/10533649.html
ln 链接文件
https://www.codesocang.com/jquerymobile/linux/2/11.html

addcompletions

    local completion_files=(
      system/core/adb/adb.bash
      system/core/fastboot/fastboot.bash
      tools/asuite/asuite.sh
    )
    # Completion can be disabled selectively to allow users to use non-standard completion.
    # e.g.
    # ENVSETUP_NO_COMPLETION=adb # -> disable adb completion
    # ENVSETUP_NO_COMPLETION=adb:bit # -> disable adb and bit completion
    for f in ${completion_files[*]}; do
        if [ -f "$f" ] && should_add_completion "$f"; then
            . $f
        fi
    done

判断是否有这个文件,或者是否文件属于 ENVSETUP_NO_COMPLETION 中需要进行补全的,然后执行 adb.bash, fastboot.bash, asuite.sh 这些脚本文件。 在tools/asuite/asuite.sh 这个脚本文件中,包含 tradefederation/core/atest/atest_completion.sh,这个文件也会被执行一下。

增加打印,可以看到输出结果:

complete f:  system/core/adb/adb.bash
should add completion:  system/core/adb/adb.bash
0
complete f:  system/core/fastboot/fastboot.bash
should add completion:  system/core/fastboot/fastboot.bash
0
complete f:  tools/asuite/asuite.sh
should add completion:  tools/asuite/asuite.sh
0
should add completion:  /home/ptz/sc200r/SC200R_Android10.0_R04_r023/tools/tradefederation/core/atest/atest_completion.sh
0
should add completion:  bit
0
    complete -F _lunch lunch

    complete -F _complete_android_module_names gomod
    complete -F _complete_android_module_names m

上面是针对 lunch这个命令 使用 _lunch 这个函数进行补全, gomod, m 也是这样。

参考: shell 中 basename 的简单使用
https://blog.51cto.com/sdsca/1903822
使用bash内置命令complete来实现参数补全
https://www.cnblogs.com/lyg-blog/p/14760145.html
使用Bash中Complete自动补全命令
https://blog.csdn.net/chen_fly2011/article/details/56830892