刚毕业时在某手机厂商任职 Android Framework 研发工程师,工作了一段时间后,深感 Framework 层的编译调试太繁琐,每次都做重复劳动.
因此决定要做一个一揽子解决方案,将整个 编译-打包-安装至手机 的流程用一行命令搞定. 于是写了一年多,写完了这个最终近2000行的脚本.
这是题主从零开始学写 bash 的最初的原因.
现在不再做 Framework 开发了,也再也没哪个脚本写的比这个罗辑更多了.最近整理脚本,觉得不分(xian)享(bai)一下太对不起这脚本了.
需求:
做过 Framework 开发的同学都知道, Framework 层中基本是一个模块一个 Android.mk, 最终的编译生成物有一个的,也有多个的. 编译产物会被放在项目根目录下的固定目录,其路径就对应着这个编译生成物应该推送至手机内的那个路径.
一般的调试流程是: 修改代码 -> 找到模块根目录编译模块 -> 编译 -> 在编译日志中找到编译产物路径 -> 根据编译产物路径将生成物 adb push 到手机
有时一个模块生成多个lib (我记得 installd 会生成7个),少推一个手机就起不来了.
有时一个修改涉及多个模块,那上面的步骤就要重复多次.
我们厂当时代码都放在了服务器上,编译完成后,要把编译生成物放在一个中间服务器(便于审核),再从中间服务器下载到本机,再从本机 push 到手机.那这个流程就又延长且繁琐了,最终每一次编译调试都要五分钟左右,还经常性的出错.
另外系统签名肯定是要放在服务器的,要签名就得上传到签名服务器. 某些模块没有签名的话,直接推也会让手机起不来.
最终要实现的脚本要完成下面事情:
1. 支持指定某个文件为参数,自动找到相应的 Android.mk 编译之
2. 支持指定多个上述文件.多个文件对应一个 Android.mk 时, duplicate 之. 对应多个时,逐个编译之
3. 分析编译日志,找到所有编译产物路径
4. 分析编译产物路径,并用 adb push 逐个将编译产物推送至手机
由于我们厂又多了个中间服务器中转过程,在以上步骤3之后的需求改为如下:
4. 将解析得到的信息汇总,生成 adbpush.sh 的脚本,内含各个编译产物要推送到手机内的路径
5. 将编译产物及 adbpush.sh 打包,并上传至中间服务器
6. 本机编写 adb_auto_push.sh 脚本,从中间服务器下载上一步的压缩包
7. 解压并对需要签名的模块签名(到签名服务器)
8. 执行压缩包内的 adbpush.sh 脚本,将编译产物推送至手机
基于中转服务器,又写了一个脚本,实现轮询中转服务器(每5秒),有新的符合规则的压缩包则下载并推送.这样看起来在服务器转一手看起来就和在本机编译体验一样了.
这个脚本最终完成后,极大的提高了相关工作效率和准确度.
代码:
公司中转服务器的那个脚本就不贴了,这里只贴在本机编译 Framework 并推送的那个脚本.
已经离开Framework相关工作太久,逐一分析太费时间了,这里就偷懒只贴代码了.
这个脚本其实是不限工作环境的,对于现在的 Android 版本,应该稍加修改也还可以用.
#!/bin/bash
# AUTHOR : liuxu
# THIS SHELL IS ENVIRONMENT INDEPENDENT
#v1.0 compile and push libs to phone
# $1 should be file or dir you wish to compile
# without $1 this sh will compile the current dir
#v1.1 add error code for exit
# 1: pre-compile error
# 2: adb error
# 3: post-compile error, most commonly caused by various compile error
# 4: adb errors, may be caused by "device not found", not critical
# 5: compile error
#v1.2 add -t option: touch file before compile. the sh will decide which file to touch, usually the last modified file.
#v2.0 2012-03-28
# add support for multi-dir/file param
# add -l option: use the given num as "lunch" command param
#v2.1 2012-04-12
# add support for "choosecombo" when setting up compile environment
#v2.2 2012-04-19
# add -d option: enable DEBUG
#v2.3 2012-07-03
# debug: when LocateAndroidmk() return $PROJECT_PATH, exit sh, or it will run "make" in project root dir.
#v2.4 2012-11-28
# 1. another way to locate $PROJECT_PATH:
# run "source build/envsetup.sh", if the return value is 0, than the $PROJECT_ROOT dir is located.
#v3.0 2013-01-17
# this sh is now independent to environment. changes:
# 1. another way to locate $PROJECT_PATH:
# just follow "gettop": see if "build/core/envsetup.mk" and "Makefile" exists.
# 2. use getopt to process params.
# 3. change the way of process params to let this shell be less dependent to environment.
# 4. when compile many files, print info after compile even if one of the files failed to compile.
# this is to ensure that we know which modules has already been compiled.
#v3.1 2013-02-01
# debug: locate wrong project root dir sometimes
#v3.2 2013-02-05
# add -u option:
# make update-api after compile
#v3.3 2013-04-15
# print current time before exit
#====================================
#global variables
#I've exported this var through .bashrc. so just commit the code here.
#DEFAULT_CONFIG_TAG="Config"
CURRENT_PATH=`pwd` #
PROJECT_NAME= #
PROJECT_PATH= #
LUNCH_NUM=
ERROR_NUM=0 #mark for error number if an error occure, also can be used as "exit" return number
B_TOUCH_ENABLED="false" #mark for use touch command before compile
B_ADB_REMOUNT="false"
B_COMPILE_SUCCEED="true"
B_PUSH_TO_PHONE="true"
B_UPDATE_API="false"
DEBUG="false"
SH_DOC=$(dirname $0)"/sh_document"
SH_DOCUMENT=$SH_DOC/document$(date +%m%d)
COM_LIBS_STORE=$SH_DOCUMENT/compiled_store #used to store compiled file path
TMP_DIR=/tmp/compile_and_push_info #temp file to store mmm output info
#this array should follow the below format:
#src_file:::compiled_lib:::phone_dir
declare -a MODULE_ARR #modules generated by compile
MODULE_ARR_LENGTH=${#MODULE_ARR[*]}
#this array should follow the below format:
#src_file:::mk_path
declare -a SRC_ARR #src file or dir
SRC_ARR_LENGTH=${#SRC_ARR[*]}
#this array is used to cache duplicated src file
#if two src_fil