接触Android的也快半年了,一直都忙着学习android 的framework、HAL,对Android的编译系统一点都不了解,在编译系统时带来了很多的不便,所以花时间详细的了解了一下,下面记录一下学习心得(由于时间仓促,有的地方理解有误,请不吝赐教)。
Android编译环境的建立以及源码的下载,Android官网给了详细的说明:http://source.android.com/source/index.html ,我就不多费口舌了,好了,进入正题。
要编译Android系统,首先再Android顶层目录下执行 : . build/envsetup.sh(注意点后有空格),. 表示执行build/envsetup.sh shell脚本。下面我们就来看看envsetup.sh都做了哪些工作:
打开envsetup.sh文件,啊......!这都是啥啊?怎么全是函数的定义?对的,envsetup.sh一部分重要的工作就是定义了很多的函数。当然,它也执行了一些命令,为了方便我把函数体都删了,只留下函数名,envsetup.sh就成了如下所示:
/*******************************envsetup.sh*********************************************/
function help()
function get_abs_build_var()
function get_build_var()
function check_product()
VARIANT_CHOICES=(user userdebug eng)
function check_variant()
function setpaths()
function printconfig()
function set_stuff_for_environment()
function set_sequence_number()
function settitle()
function addcompletions()
function choosetype()
function chooseproduct()
function choosevariant()
function choosecombo()
unset LUNCH_MENU_CHOICES
function add_lunch_combo()
add_lunch_combo full-eng
add_lunch_combo full_x86-eng
add_lunch_combo vbox_x86-eng
function print_lunch_menu()
function lunch()
function _lunch()
complete -F _lunch lunch
function tapas()
function gettop
function m()
function findmakefile()
function mm()
function mmm()
function croot()
function cproj()
function pid()
function systemstack()
function gdbclient()
case `uname -s` in
Darwin)
function sgrep()
{
find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|S|java|xml|sh|mk)' -print0 | xargs -0 grep --color -n "$@"
}
;;
*)
function sgrep()
{
find . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.\(c\|h\|cpp\|S\|java\|xml\|sh\|mk\)' -print0 | xargs -0 grep --color -n "$@"
}
;;
esac
function jgrep()
function cgrep()
function resgrep()
case `uname -s` in
Darwin)
function mgrep()
{
find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*/(Makefile|Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -print0 | xargs -0 grep --color -n "$@"
}
function treegrep()
{
find -E . -name .repo -prune -o -name .git -prune -o -type f -iregex '.*\.(c|h|cpp|S|java|xml)' -print0 | xargs -0 grep --color -n -i "$@"
}
;;
*)
function mgrep()
{
find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '(.*\/Makefile|.*\/Makefile\..*|.*\.make|.*\.mak|.*\.mk)' -type f -print0 | xargs -0 grep --color -n "$@"
}
function treegrep()
{
find . -name .repo -prune -o -name .git -prune -o -regextype posix-egrep -iregex '.*\.(c|h|cpp|S|java|xml)' -type f -print0 | xargs -0 grep --color -n -i "$@"
}
;;
esac
function getprebuilt
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function key_home()
function key_back()
function key_menu()
function smoketest()
function runtest()
function godir ()
function set_java_home()
if [ "x$SHELL" != "x/bin/bash" ]; then
case `ps -o command -p $$` in
*bash*)
;;
*)
echo "WARNING: Only bash is supported, use of other shell would lead to erroneous results"
;;
esac
fi
for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
do
echo "including $f"
. $f
done
unset f
addcompletions
/*************************************end*************************************************/
经过这样的处理后,文件小了很多,只有100多行了,看着是不是舒服多了?在这100行多一点的代码里,其实只有相当一小部分是我们需要注意的,上面用红色标记的地方,第一部分:
add_lunch_combo full-eng
add_lunch_combo full_x86-eng
add_lunch_combo vbox_x86-eng
add_lunch_combo 是这个文件里定义的函数,现在我们来看看其函数体:
/*************************************begin***********************************************/
function add_lunch_combo()
{
local new_combo=$1
local c
for c in ${LUNCH_MENU_CHOICES[@]} ; do
if [ "$new_combo" = "$c" ] ; then
return
fi
done
LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}
/*************************************end*************************************************/
这个函数做的事很简单,相信大家都能看明白,如果看不懂的话,去baidu好好学习一下shell编程吧!它就是将add_lunch_combo 后面的参数加入到变量LUNCH_MENU_CHOICES中。
红色标记的第二部分:
for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
do
echo "including $f"
. $f
done
unset f
这一段代码就是查找 vendor/*/、vendor/*/*/、device/*/*/目录下的vendorsetup.sh文件,并执行找到的vendorsetup.sh文件,我们来看一个vendorsetup.sh文件:
/***************************device/ti/panda/vendorsetup.sh***************************/
#
# Copyright (C) 2011 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
add_lunch_combo full_panda-eng
/*************************************end*************************************************/
里面只有一句代码:add_lunch_combo full_panda-eng,这个前面分析了就不说了。
总结一下,. build/envsetup.sh主要工作有:
1. 定义很多很多的函数。
2. 把默认的product名字full-eng、full_x86-eng、vbox_x86-eng加入到 LUNCH_MENU_CHOICES 变量中。
3. 查找vendor/*/、vendor/*/*/、device/*/*/目录下的vendorsetup.sh,将开发者的product名字加入到LUNCH_MENU_CHOICES 变量中。
. build/envsetup.sh 后,就是lunch命令了,后续会分析,尽情期待。