最近要修改product 以及buildtype,学习了一下android的编译准备工作,以此记录。
一.source build/envsetup.sh
这个命令编译过android源码的人都不会陌生,也是起始命令。
字面意思就是设置环境变量,envsetup.sh中:
function hmm() {
cat <<EOF
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch: lunch <product_name>-<build_variant>
- tapas: tapas [<App1> <App2> ...] [arm|x86|mips] [eng|userdebug|user]
- croot: Changes directory to the top of the tree.
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory.
- mmm: Builds all of the modules in the supplied directories.
- cgrep: Greps on all local C/C++ files.
- jgrep: Greps on all local Java files.
- resgrep: Greps on all local res/*.xml files.
- godir: Go to the directory containing a file.
Look at the source to view more functions. The complete list is:
EOF
T=$(gettop)
local A
A=""
for i in `cat $T/build/envsetup.sh | sed -n "/^function /s/function \([a-z_]*\).*/\1/p" | sort`; do
A="$A $i"
done
echo $A
}
依次将function *() 方法加载到环境变量中。
function get_abs_build_var() # 获取绝对变量
function get_build_var() # 获取绝对变量
function check_product() # 检查product
function check_variant() # 检查变量
function setpaths() # 设置文件路径
function printconfig() # 打印配置
function set_stuff_for_environment() # 设置环境变量
function set_sequence_number() # 设置序号
function settitle() # 设置标题
function choosetype() # 设置type
function chooseproduct() # 设置product
function choosevariant() # 设置variant
function tapas() # 功能同choosecombo
function choosecombo() # 设置编译参数
function add_lunch_combo() # 添加lunch项目
function print_lunch_menu() # 打印lunch列表
function lunch() # 配置lunch
function m() # make from top
function findmakefile() # 查找makefile
function mm() # make from current directory
function mmm() # make the supplied directories
function croot() # 回到根目录
function cproj()
function pid()
function systemstack()
function gdbclient()
function jgrep() # 查找java文件
function cgrep() # 查找c/cpp文件
function resgrep()
function tracedmdump()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function godir () # 跳到指定目录
这个脚本在加载完命令函数之后,就会去加载android的编译选项:
# add the default one here
add_lunch_combo full-eng
add_lunch_combo full_x86-eng
add_lunch_combo vbox_x86-eng
add_lunch_combo full_mips-eng
调用的是 add_lunch_combo 函数:
function add_lunch_combo()
{
local new_combo=$1 # 获得add_lunch_combo被调用时的参数
local c
# 依次遍历LUNCH_MENU_CHOICES里的值,其实该函数第一次调用时,该值为空
for c in ${LUNCH_MENU_CHOICES[@]} ; do
if [ "$new_combo" = "$c" ] ; then # 如果参数里的值已经存在于LUNCH_MENU_CHOICES变量里,则返回
return
fi
done
# 如果参数的值不存在,则添加到LUNCH_MENU_CHOICES变量里
LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
}
往下走 :
# Execute the contents of any vendorsetup.sh files we can find.
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
这是到指定的路径下去找vendorsetup.sh脚本并执行,这些脚本就是自定义的工程了,需要执行 add_lunch_combo函数 将我们的产品名以及编译属性添加到LUNCH_MENU_CHOICES 以供后面lunch 时选择!
add_lunch_combo gotechcn-userdebug
我这里添加的选项结构 gotechcn 就是产品名称,编译类型就是 userdebug 中间以“-”分开
可以看到如果找到了就会打印including **,我这的工程是这样的:
including device/asus/grouper/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/generic/armv7-a-neon/vendorsetup.sh
including device/generic/armv7-a/vendorsetup.sh
including device/generic/mips/vendorsetup.sh
including device/generic/x86/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/mstar/gotechcn/vendorsetup.sh
二.编译选项的区别以及作用:
上面看到设置了编译选项为userdebug,android 的编译选项分3种:
eng: 工程机,
user:最终用户机
userdebug:调试测试机
android的android.mk 文件中有一个配置选项: LOCAL_MODULE_TAGS 配置成什么就是在什么版本的情况下才会被编译进系统!
LOCAL_MODULE_TAGS := optional
这个代表不管编译选项是什么 都编译进去。
三种类型编译区别如下:
#1.eng,那么其编译进去的内容包括:
· Intended for platform-level debugging
· Installs modules tagged with: eng, debug, user, and/or development
· Installs non-APK modules that have no tags specified
· Installs APKs according to the product definition files, in addition to tagged APKs
· Sets ro.secure=1
· Sets ro.debuggable=0
· Sets ro.kernel.android.checkjni=1
· adbd is enabled by default
#2.user,那么其编译进去的内容包括:
· Intended to be the final release
· Installs modules tagged as user
· Installs non-APK modules that have no tags specified
· Installs APKs according to the product definition files (tags are ignored for APK modules)
· Sets ro.secure=1
· Sets ro.debuggable=0
· adbd is disabled by default
#3.userdebug,那么其编译进去的内容包括:
the same as user, except:
· Intended for limited debugging
· Installs modules tagged with debug
· Sets ro.debuggable=1
· adbd is enabled by default
这是之前版本的控制,目前以我的android 4.2 分析的请参考: Android——编译安装Module的控制因素
三.lunch
在做了前面的准备之后就可以在终端运行lunch命令来选择将要编译的成品类型了。
调用到:
function lunch()
{
local answer
if [ "$1" ] ; then
# lunch后面直接带参数
answer=$1
else
# lunch后面不带参数,则打印处所有的target product和variant菜单提供用户选择
print_lunch_menu
echo -n "Which would you like? [full-eng] "
read answer
fi
local selection=
if [ -z "$answer" ]
then
# 如果用户在菜单中没有选择,直接回车,则为系统缺省的full-eng 为第一个选项
selection=generic-eng
elif [ "$answer" = "simulator" ]
then
# 如果是模拟器
selection=simulator
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
# 如果answer是选择菜单的数字,则获取该数字对应的字符串
if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
then
selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
fi
# 如果 answer字符串匹配 *-*模式(*的开头不能为-)
elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
then
selection=$answer
fi
if [ -z "$selection" ]
then
echo
echo "Invalid lunch combo: $answer"
return 1
fi
# special case the simulator
if [ "$selection" = "simulator" ]
then
# 模拟器模式
export TARGET_PRODUCT=sim
export TARGET_BUILD_VARIANT=eng
export TARGET_SIMULATOR=true
export TARGET_BUILD_TYPE=debug
else
# 将 product-variant模式中的product分离出来
local product=$(echo -n $selection | sed -e "s/-.*$//")
check_product $product
# 检查之,调用关系 check_product()->get_build_var()中调用了make命令 “ make --no-print-directory -C "$T" -f build/core/config.mk dumpvar-$1 ” 后面另开一篇再来详细跟进去学习!
if [ $? -ne 0 ]
then
echo
echo "** Don't have a product spec for: '$product'"
echo "** Do you have the right repo manifest?"
product=
fi
# 将 product-variant模式中的variant分离出来
local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
# 检查之,看看是否在 (user userdebug eng) 范围内
check_variant $variant
if [ $? -ne 0 ]
then
echo
echo "** Invalid variant: '$variant'"
echo "** Must be one of ${VARIANT_CHOICES[@]}"
variant=
fi
if [ -z "$product" -o -z "$variant" ]
then
echo
return 1
fi
# 导出环境变量,这里很重要,因为后面的编译系统都是依赖于这里定义的几个变量的
export TARGET_PRODUCT=$product
export TARGET_BUILD_VARIANT=$variant
export TARGET_BUILD_TYPE=release
#调用函数设置环境变量,函数全部在envsetup.sh中
set_stuff_for_environment
# 打印一些主要的变量, 调用关系 printconfig()->get_build_var()->build/core/config.mk->build/core/envsetup.mk 比较罗嗦,不展开了
printconfig
}
当选择之后,check 和 set 成功之后 就会打印出来:
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=4.2.1
TARGET_PRODUCT=full_gotechcn
TARGET_BUILD_VARIANT=userdebug
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a-neon
HOST_ARCH=x86
HOST_OS=linux
HOST_OS_EXTRA=Linux-3.8.0-19-generic-x86_64-with-Ubuntu-13.04-raring
HOST_BUILD_TYPE=release
BUILD_ID=MK04
OUT_DIR=out
============================================
到这里,make之前的准备工作已经做完了,在上面其中对product的控制检测都是通过调用check_product()到makefile体系中去查询设置相关变量的,如果新添加product就需要牵扯到里面,另外可以在build.prop中查看这些编译选项有没有设置成功!