刚毕业时在某手机厂商任职 Android Framework 研发工程师,工作了一段时间后,深感 Framework 层的编译调试太繁琐,每次都做重复劳动.
因此决定要做一个一揽子解决方案,将整个 编译-打包-安装至手机 的流程用一行命令搞定. 于是写了一年多,写完了这个最终近2000行的脚本.
这是题主从零开始学写 bash 的最初的原因.
现在不再做 Framework 开发了,也再也没哪个脚本写的比这个罗辑更多了.最近整理脚本,觉得不分(xian)享(bai)一下太对不起这脚本了.
需求:
做过 Framework 开发的同学都知道, Framework 层中基本是一个模块一个 Android.mk, 最终的编译生成物有一个的,也有多个的. 编译产物会被放在项目根目录下的固定目录,其路径就对应着这个编译生成物应该推送至手机内的那个路径.
一般的调试流程是:
修改代码 -> 找到模块根目录编译模块 -> 编译 -> 在编译日志中找到编译产物路径 -> 根据编译产物路径将生成物 adb push 到手机
有时一个模块生成多个lib (我记得 installd 模块会生成7个),少推一个手机就起不来了.
有时一个修改涉及多个模块,那上面的步骤就要重复多次.
我们厂当时代码都放在了服务器上,编译完成后,要把编译生成物放在一个中间服务器(便于审核),再从中间服务器下载到本机,再从本机 push 到手机.那这个流程就又延长且繁琐了,最终每一次编译调试都要五分钟左右,还经常性的出错.
另外系统签名肯定是要放在服务器的,要签名就得上传到签名服务器. 某些模块没有签名的话,直接推也会让手机起不来.
最终要实现的脚本要完成下面事情:
- 支持指定某个文件为参数,自动找到相应的 Android.mk 编译之
- 支持指定多个上述文件.多个文件对应一个 Android.mk 时, duplicate 之. 对应多个时,逐个编译之
- 分析编译日志,找到所有编译产物路径
- 分析编译产物路径,并用 adb push 逐个将编译产物推送至手机
由于我们厂又多了个中间服务器中转过程,在以上步骤3之后的需求改为如下:
- 将解析得到的信息汇总,生成 adbpush.sh 的脚本,内含各个编译产物要推送到手机内的路径
- 将编译产物及 adbpush.sh 打包,并上传至中间服务器
- 本机编写 adb_auto_push.sh 脚本,从中间服务器下载上一步的压缩包
- 解压并对需要签名的模块签名(到签名服务器)
- 执行压缩包内的 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_file have the same mk_path, one of them is marked as duplicated
#element should be path based on PROJECT_PATH
declare -a DUPLICATED_SRC_ARR
DUPLICATED_SRC_ARR_LENGTH=${#DUPLICATED_SRC_ARR[*]}
#====================================
#util functions
trap "CLEAR_WORK" EXIT
DEBUG() {
if [ "$DEBUG" == "true" ]; then
$@
fi
}
CLEAR_WORK() {
if [ -e $TMP_DIR ]; then
sudo rm -rf $TMP_DIR
fi
local current_time="`date +%x` `date +%T`"
echo "* Time on exit: $current_time"
echo
}
function ShellHelp() {
cat < /dev/null
while true; do
#DEBUG echo "LocateAndroidmk, path: $path; ret path: $ret_path"
if [ -f $ret_path/Android.mk ]; then
break
elif [ "$ret_path" == "/" ]; then
echo "/"
return
fi
cd ..
ret_path=$(pwd)
done
cd $cur_path > /dev/null
echo $ret_path
}
#locate project root dir
#$1 should be a full path of a file or dir
#without $1 this function will check current path
#yield the path if found, or "/" if not found
function LocateProjectRoot() {
local path
local cur_path=$(pwd)
local tmp_path
local prj_path
if [ $# -eq 0 ]; then
path=$(pwd)
elif [ -f $1 ]; then
path=$(dirname $1 | xargs readlink -f)
else
path=$(readlink -f $1)
fi
tmp_path=$path
cd $tmp_path > /dev/null
while true; do
if [ -f build/core/envsetup.mk -a -f Makefile ]; then
break
elif [ "$tmp_path" == "/" ]; then
echo "/"
return
fi
cd ..
tmp_path=$(pwd)
done
cd $cur_path > /dev/null
prj_path=$tmp_path
if [ $? -eq 0 ]; then
echo $prj_path
else
echo "/"
fi
}
function PrintVariableInfo() {
[ "$DEBUG" == "false" ] && return
echo "===================================="
echo "PROJECT_NAME=$PROJECT_NAME"
echo "PROJECT_PATH=$PROJECT_PATH"
echo "LUNCH_NUM=$LUNCH_NUM"
echo "B_TOUCH_ENABLED=$B_TOUCH_ENABLED"
echo "B_PUSH_TO_PHONE=$B_PUSH_TO_PHONE"
echo "B_ADB_REMOUNT=$B_ADB_REMOUNT"
for src in ${SRC_ARR[*]}; do
echo "SRC_ARR : $src"
done
for module in ${MODULE_ARR[*]}; do
echo "MODULE_ARR : $module"
done
echo "===================================="
}
#====================================
#env related functions
#get touch file between two dirs
#only find files in $1 and superior dir of $1, until we reach $2
#$1 and $2 should be full path of a dir
#$1 should be subdir of $2
function PickTouchFile() {
local ret=""
if [ ! -d $1 -o ! -d $2 ]; then
echo $ret
return
fi
local begin_file=$(readlink -f $1)
local end_file=$(readlink -f $2)
if [[ "$begin_file" != "$end_file"* && ! $begin_file -ef $end_file ]]; then
echo $ret
return
fi
local bn; local suffix
local current_dir=$begin_file
local end_dir=$(cd $end_file/.. ; pwd)
while [ ! $end_dir -ef $current_dir ]; do
DEBUG echo "DEBUG, search in $current_dir"
cd $current_dir
local tmp_arr=$(find $current_dir -maxdepth 1 -type f)
if [ ${#tmp_arr[*]} -eq 0 ]; then
#no file type in current dir, continue
continue
fi
touch_file_arr=($(find $current_dir -maxdepth 1 -type f | xargs ls -1t | sed '/\/.git\//d; /Android.mk/d' | sed -n '1,10'p))
if [ "$DEBUG" == "true" ]; then
for tfa in ${touch_file_arr[*]}; do
echo "DEBUG, SrcArrAdd, touch_file_arr : $tfa"
done
fi
for fff in ${touch_file_arr[*]}; do
bn=$(basename $fff)
suffix=${bn#*.}
if [ "$suffix" == "c" -o \
"$suffix" == "cpp" -o \
"$suffix" == "h" -o \
"$suffix" == "java" -o \
"$suffix" == "xml" -o \
"$suffix" == "rc" ]; then
ret=$fff
echo $ret
return
fi
done
current_dir=$(cd .. ; pwd)
done
unset touch_file_arr
echo $ret
return
}
#add element to SRC_ARR
#src_file:::mk_path
#src_file & mk_path are paths based on $PROJECT_PATH
#$1 should be full path of src_file
function SrcArrAdd() {
DEBUG echo "+++++++++++++++++++++++++++"
DEBUG echo "DEBUG, SrcArrAdd, \$1=$1"
if [ ! -e $1 ]; then
echo
echo "* SrcArrAdd, $1 does not exist. should be full path of a dir or file."
return 1
fi
local mk_path=$(LocateAndroidmk $1)
DEBUG echo "DEBUG, SrcArrAdd, mk_path=$mk_path"
if [ "$mk_path" == "/" ]; then
echo
echo "* SrcArrAdd, could not locate a validate Android.mk for the below path, pls check."
echo $1
echo
ERROR_NUM=1
exit $ERROR_NUM
fi
local touch_file
#touch the newest file in $1
#if no file exist, touch the newest file in mk_path
if [ "$B_TOUCH_ENABLED" == "true" ]; then
if [ -f $1 ]; then
touch_file=$1
else
#cache an arr of the 10 newest files
#so that if the first newest file could not be used as touch file, use the second, etc.
touch_file=$(PickTouchFile $1 $mk_path)
#exit the shell here if DEBUG and TOUCH is enabled, or else it will bring more unnecessary errors
DEBUG exit $ERROR_NUM
fi
DEBUG echo "DEBUG, SrcArrAdd, for $1, touch_file=$touch_file"
if [ -f $touch_file ]; then
touch $touch_file
else
echo "* fail to locate a proper file to touch."
echo "* possibly cd to a more specified dir (sub dir of current dir) will solve the problem."
echo "* it is best if you would use a file type as param."
ERROR_NUM=1
exit $ERROR_NUM
fi
fi
local param_full_path=$(readlink -f $1)
local pj_mk_path=$(echo $mk_path | awk -F "$PROJECT_PATH/" '{print $2}')
local pj_src_file=$(echo $param_full_path | awk -F "$PROJECT_PATH/" '{print $2}')
SRC_ARR[$SRC_ARR_LENGTH]="$pj_src_file:::$pj_mk_path"
SRC_ARR_LENGTH=${#SRC_ARR[*]}
DEBUG echo "+++++++++++++++++++++++++++"
}
#====================================
#compile related functions
#setup compile environment
function SetupEnv() {
if [ ! -f $PROJECT_PATH/$PROJECT_NAME.$DEFAULT_CONFIG_TAG ]; then
echo
echo "* cannot find .config file !!!"
ERROR_NUM=1
return $ERROR_NUM
fi
cd $PROJECT_PATH > /dev/null
. $PROJECT_PATH/build/envsetup.sh
if [ "$LUNCH_NUM" == "" ]; then
LUNCH_NUM=$(sed -n '/^DEFAULT_LUNCH_NUM/'p $PROJECT_PATH/$PROJECT_NAME.$DEFAULT_CONFIG_TAG | awk -F "=" '{print $2}')
COMBO=$(sed -n '/^DEFAULT_COMBO/'p $PROJECT_PATH/$PROJECT_NAME.$DEFAULT_CONFIG_TAG | awk -F "=" '{print $2}')
if [ ! "$LUNCH_NUM" == "" ]; then
lunch $LUNCH_NUM
elif [ ! "$COMBO" == "" ]; then
choosecombo $COMBO
else
echo
echo "* no validate option for 'lunch' command. use -l to specify a lunch number."
ShellHelp
ERROR_NUM=1
return $ERROR_NUM
fi
fi
cd - > /dev/null
}
#add element to MODULE_ARR
#src_file:::compiled_lib:::phone_dir
#src_file & compiled_lib are paths based on $PROJECT_PATH
#$1 should be full path of src_file
#$2 should be full path of compiled_lib
function ModuleArrAdd() {
if [ ! -e $1 ]; then
echo
echo "* ModuleArrAdd, $1 does not exist. should be full path a file"
return 1
fi
local pj_src_file=$(echo $1 | awk -F "$PROJECT_PATH/" '{print $2}')
local pj_compiled_lib=$(echo $2 | awk -F "$PROJECT_PATH/" '{print $2}')
local product_name=$(echo $pj_compiled_lib | awk -F "/" '{print $4}')
local file_basename=$(basename $2)
local phone_dir=$(echo $2 | awk -F "out/target/product/$product_name" '{print $2}' | awk -F "$file_basename" '{print $1}')
MODULE_ARR[$MODULE_ARR_LENGTH]="$pj_src_file:::$pj_compiled_lib:::$phone_dir"
MODULE_ARR_LENGTH=${#MODULE_ARR[*]}
}
#compile all elements in SRC_ARR and decipher compile info
#src_file:::compiled_lib:::phone_dir
function DecipherCompileInfo() {
local mk_dir; local pj_file ;local tmp_file
[ -d $TMP_DIR ] || mkdir $TMP_DIR
local compiled_lib_arr
local uniq_mk_arr
local uniq_mk_arr_length
local is_mk_uniq="true"
for n in ${SRC_ARR[*]}; do
mk_dir=$(echo $n | awk -F ":::" '{print $2}')
pj_file=$(echo $n | awk -F ":::" '{print $1}')
tmp_file=$(basename $PROJECT_PATH/$pj_file)"_compile_info_"$(date +%m%d%H%M%S)
#duplicate src_file with the same mk_path
DEBUG echo "DEBUG, mk_dir : $mk_dir ; uniq_mk_arr : ${uniq_mk_arr[*]}"
for uma in ${uniq_mk_arr[*]}; do
if [ $PROJECT_PATH/$uma -ef $PROJECT_PATH/$mk_dir ]; then
is_mk_uniq="false"
DUPLICATED_SRC_ARR[$DUPLICATED_SRC_ARR_LENGTH]=$pj_file
DUPLICATED_SRC_ARR_LENGTH=${#DUPLICATED_SRC_ARR[*]}
break
fi
done
DEBUG echo "DEBUG, DUPLICATED_SRC_ARR : ${DUPLICATED_SRC_ARR[*]}"
DEBUG echo "is_mk_uniq : $is_mk_uniq"
if [ "$is_mk_uniq" == "false" ]; then
is_mk_uniq="true"
continue
fi
#compile
if [ "$mk_dir" == "" -o "$mk_dir" == "/" ]; then
echo "* Should not compile in root dir of a project !"
ERROR_NUM=1
exit $ERROR_NUM
fi
echo "--------------------------------------------------------------------------------"
echo "compile ....."
echo "src file : $pj_file"
echo "mk path : $mk_dir"
echo "--------------------------------------------------------------------------------"
echo
cd $PROJECT_PATH/$mk_dir > /dev/null
#TODO: perhaps we should use "make" instead of such command as "mm"
mm | tee -a $TMP_DIR/$tmp_file
if [ "$B_UPDATE_API" == "true" ]; then
echo
echo "make update-api"
echo
cd $PROJECT_PATH
make update-api
fi
cd - > /dev/null
echo
#duplicate src_file with the same mk_path
uniq_mk_arr[$uniq_mk_arr_length]=$mk_dir
uniq_mk_arr_length=${#uniq_mk_arr[*]}
#decipher
compiled_lib_arr=($(cat $TMP_DIR/$tmp_file | sed -n '/^Install: /p' | awk -F ": " '{print $2}'))
if [ "$DEBUG" == "true" ]; then
for cla in ${compiled_lib_arr[*]}; do
DEBUG echo "DEBUG, decipher libs from compile info: $cla"
done
fi
if [ ${#compiled_lib_arr[*]} -eq 0 ]; then
B_COMPILE_SUCCEED="false"
echo "--------------------------------------------------------------------------------"
echo "* Error occur while compile below file or dir. pls check it."
echo "$PROJECT_PATH/$pj_file"
echo
JustShowInfo
ERROR_NUM=5
exit $ERROR_NUM
fi
if [ ! -d $SH_DOC ]; then
mkdir $SH_DOC
fi
if [ ! -d $SH_DOCUMENT ]; then
mkdir $SH_DOCUMENT
fi
for m in ${compiled_lib_arr[*]}; do
DEBUG echo "DEBUG, PROJECT_PATH/pj_file : $PROJECT_PATH/$pj_file"
DEBUG echo "DEBUG, PROJECT_PATH/m : $PROJECT_PATH/$m"
ModuleArrAdd $PROJECT_PATH/$pj_file $PROJECT_PATH/$m
echo $PROJECT_PATH/$m >> $COM_LIBS_STORE
done
done
}
#====================================
#adb related functions
function ReadyADBRemount() {
[ "$UID" = "0" ] && SUDO= || SUDO=sudo
# if [ -f $PROJECT_PATH/out/host/linux-x86/bin/adb ]; then
# ADB="$SUDO $PROJECT_PATH/out/host/linux-x86/bin/adb"
# else
# ADB="$SUDO /usr/local/bin/adb"
# fi
ADB="$SUDO /usr/local/bin/adb"
DEBUG echo "ADB: $ADB"
local adb_info1=$($ADB remount | sed -n '$'p)
local retry_count=1 #just retry once
local i=0
while [ $retry_count -ne $i ]; do
echo "$adb_info1"
if [ "$adb_info1" == "remount succeeded" ]; then
B_ADB_REMOUNT="true"
return
else
echo "* retry remount."
$ADB kill-server
$ADB root
adb_info1=$($ADB remount | sed -n '$'p)
fi
let i++
done
echo "* cannot remount, please push libs manually."
ERROR_NUM=4
return
}
function JustShowInfo() {
local src_file
local phone_dir #to where we will put the compiled file
local compiled_lib
if [ $ERROR_NUM -ne 0 -a $ERROR_NUM -ne 4 ]; then
echo
echo "* some problem happened while running this sh. better not push any libs to the phone. pls check. ERROR_NUM=$ERROR_NUM"
echo
exit $ERROR_NUM
fi
if [ $MODULE_ARR_LENGTH -eq 0 ]; then
echo
echo "* No module generated, exit."
echo
ERROR_NUM=3
exit $ERROR_NUM
fi
#display duplicated src arr
echo "--------------------------------------------------------------------------------"
if [ $DUPLICATED_SRC_ARR_LENGTH -ne 0 ]; then
echo
for ddd in ${DUPLICATED_SRC_ARR[*]}; do
echo "* Duplicate Src File : $ddd"
done
fi
for n in ${MODULE_ARR[*]}; do
src_file=$(echo $n | awk -F ":::" '{print $1}')
compiled_lib=$(echo $n | awk -F ":::" '{print $2}')
phone_dir=$(echo $n | awk -F ":::" '{print $3}')
if [ "$compiled_lib" == "" ]; then
echo "* no .so or .jar etc. was generated from below file or dir. pls check it."
echo "$src_file"
continue
fi
echo
echo "* Project name : $PROJECT_NAME"
echo "* Src File or Dir : $src_file"
echo "* File Got From Compile : $compiled_lib"
echo "* using below command to push to phone: "
echo "sudo adb push $PROJECT_PATH/$compiled_lib $phone_dir"
echo
echo "--------------------------------------------------------------------------------"
done
}
function PushToPhone() {
local src_file
local phone_dir #to where we will put the compiled file
local compiled_lib
if [ $ERROR_NUM -ne 0 -a $ERROR_NUM -ne 4 ]; then
echo
echo "some problem happened while running this sh. better not push any libs to the phone. pls check. ERROR_NUM=$ERROR_NUM"
echo
exit $ERROR_NUM
fi
if [ $MODULE_ARR_LENGTH -eq 0 ]; then
echo
echo "* No module to be pushed, exit."
echo
ERROR_NUM=3
exit $ERROR_NUM
fi
#display duplicated src arr
if [ $DUPLICATED_SRC_ARR_LENGTH -ne 0 ]; then
echo
for ddd in ${DUPLICATED_SRC_ARR[*]}; do
echo "* Duplicate Src File : $ddd"
done
fi
for n in ${MODULE_ARR[*]}; do
src_file=$(echo $n | awk -F ":::" '{print $1}')
compiled_lib=$(echo $n | awk -F ":::" '{print $2}')
phone_dir=$(echo $n | awk -F ":::" '{print $3}')
if [ "$compiled_lib" == "" ]; then
echo "* no .so or .jar etc. was generated from below file or dir. pls check it."
echo "$src_file"
continue
fi
echo
echo "* Project name : $PROJECT_NAME"
echo "* Src File or Dir : $src_file"
echo "* File Got From Compile : $compiled_lib"
if [ "$B_ADB_REMOUNT" == "false" ]; then
echo "* adb remount fail. pls push libs manually. using below command: "
echo "sudo adb push $PROJECT_PATH/$compiled_lib $phone_dir"
echo
continue
else
echo
echo "pushing ..."
echo "$PROJECT_PATH/$compiled_lib --> $phone_dir"
echo
fi
if [ -n "$compiled_lib" -a -n "$phone_dir" ]; then
$ADB push $PROJECT_PATH/$compiled_lib $phone_dir
else
echo "* empty string caused by unknown error."
echo
ERROR_NUM=3
return
fi
done
}
#====================================
#process args and opts
#process options
function ProcessOptions() {
while getopts ":txdul:" opt; do
DEBUG echo "opt: $opt"
case "$opt" in
"t")
B_TOUCH_ENABLED="true"
;;
"x")
B_PUSH_TO_PHONE="false"
;;
"u")
B_UPDATE_API="true"
;;
"d")
DEBUG="true"
;;
"l")
DEBUG echo "DEBUG, ProcessParam, LUNCH_NUM=$LUNCH_NUM"
if [ $(IsInterger $OPTARG) == "true" ]; then
LUNCH_NUM=$OPTARG
else
echo "* you need to specify a digit value for option -l"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
fi
;;
"?")
#Unknown option
echo "* unknown option: $opt"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
;;
":")
#an option needs a value, which, however, is not presented
echo "* option $OPTARG needs a value, but it is not presented"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
;;
*)
#unknown error, should not occur
echo "* unknown error while processing options and params"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
;;
esac
done
return $OPTIND
}
#process params
function ProcessParams() {
DEBUG echo "params: $@"
if [ $# -eq 0 ]; then
#no params, just print help
ShellHelp
#return 1 here to avoid father operation such as "adb reboot"
exit 1
fi
local pj_root
local pj_name
for param in $@; do
#process and store params into array
if [ -e $param ]; then
local full_path=$(readlink -f $param)
pj_root=$(LocateProjectRoot $full_path)
DEBUG echo "+++++++++++++++++++++++++++"
DEBUG echo "ProcessParams, param : $param"
DEBUG echo "ProcessParams, pj_root : $pj_root"
DEBUG echo "+++++++++++++++++++++++++++"
if [ "$pj_root" == "/" ]; then
echo
echo "* target dir is not in any project!"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
fi
if [ "$PROJECT_NAME" == "" ]; then
PROJECT_NAME=$(basename $pj_root)
PROJECT_PATH=$pj_root
else
if [ ! "$pj_root" == "$PROJECT_PATH" ]; then
echo
echo "* for now we do not support compile in different projects. pls compile them one by one."
ERROR_NUM=6
exit $ERROR_NUM
fi
fi
SrcArrAdd $param
else
echo "* param does not exist! $param"
ShellHelp
ERROR_NUM=1
exit $ERROR_NUM
fi
done
}
#====================================
#main
ProcessOptions "$@"
param_start=$?
ProcessParams "${@:$param_start}"
unset param_start
SetupEnv
DEBUG PrintVariableInfo
DecipherCompileInfo
echo
echo "--------------------------------------------------------------------------------"
echo
if [ "$B_PUSH_TO_PHONE" == "true" ]; then
ReadyADBRemount
PushToPhone
else
JustShowInfo
fi
exit $ERROR_NUM
另: 这个脚本成型于4年前,很多地方处理的并不成熟,
比如找 git 项目根目录的办法
比如 sed 命令的使用
比如 true false 变量的处理
等等等等. 即使是截止到写这篇文章的时间点, 题主的bash水平依然有很多不足之处.
说人话就是: 学无止境,欢迎指教,和平讨论~.