创建属于自己的产品
创建属于自己的产品
我们先梳理清楚我们在编译的时候,这个过得干了啥!!
首次我们是设置环境
aosp@ubuntu:~/android5.1$ source build/envsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/asus/deb/vendorsetup.sh
including device/asus/grouper/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including sdk/bash_completion/adb.bash
然后加载编译目标
aosp@ubuntu:~/android5.1$ lunch
You're building on Linux
Lunch menu... pick a combo:
1. aosp_arm-eng
2. aosp_arm64-eng
3. aosp_mips-eng
4. aosp_mips64-eng
5. aosp_x86-eng
6. aosp_x86_64-eng
7. aosp_hammerhead-userdebug
8. aosp_mako-userdebug
9. aosp_manta-userdebug
10. mini_emulator_arm64-userdebug
11. mini_emulator_x86_64-userdebug
12. m_e_arm-userdebug
13. mini_emulator_x86-userdebug
14. mini_emulator_mips-userdebug
15. aosp_shamu-userdebug
16. aosp_flo-userdebug
17. aosp_tilapia-userdebug
18. aosp_deb-userdebug
19. aosp_grouper-userdebug
20. full_fugu-userdebug
21. aosp_fugu-userdebug
22. aosp_flounder-userdebug
Which would you like? [aosp_arm-eng]
okay,到这里,我们的疑问就来了,这些构建目标是怎么来的呢?
首先是我们的lunch命令,如果不source build/envsetup.sh
是没有这个命令的。
我们可以看一下build/envsetup.sh
脚本的代码,可以发现launch就在里面
function lunch()
{
# 选项结果,也就是我们前面输入的5
local answer
# 有携带参数,直接结果就是参数了
if [ "$1" ] ; then
answer=$1
else
# 没有携带参数,那么就输出lunch列表
#print_lunch_menu就是我们看到的列表了
print_lunch_menu
echo -n "Which would you like? [aosp_arm-eng] "
# 读取选项值
read answer
fi
....省略代码....
}
先看到这里,我们就知道了,列表是print_lunch_menu输出的
我们接下来的课程,创建属于自己的产品,就是在这里有个编译选项,然后去编译我们自己的内容。
所以呢,我们看看这个输出列表是怎么来的。
function print_lunch_menu()
{
local uname=$(uname)
echo
echo "You're building on" $uname
echo
echo "Lunch menu... pick a combo:"
local i=1
local choice
# 列表在这里:
for choice in ${LUNCH_MENU_CHOICES[@]}
do
echo " $i. $choice"
i=$(($i+1))
done
echo
}
那么我们就看看LUNCH_MENU_CHOICES这个是在哪里赋值的
# Clear this variable. It will be built up again when the vendorsetup.sh
# files are included at the end of this file.
unset LUNCH_MENU_CHOICES
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)
}
# add the default one here
add_lunch_combo aosp_arm-eng
add_lunch_combo aosp_arm64-eng
add_lunch_combo aosp_mips-eng
add_lunch_combo aosp_mips64-eng
add_lunch_combo aosp_x86-eng
add_lunch_combo aosp_x86_64-eng
这样子,前6个就有了,我们可以做一下实验,注释掉看看。
修改了envsetup.sh文件,需要重新载入到环境中,再lunch一次,我们就会发现没了。
okay,到这里可以确定,这个是在这里添加了。
接下来呢,我们探讨一下其他的是在哪里添加的。同学们凭借着自己的经验,知道如何寻找出来吗?
如果你不知道的,可以搜索,如果你代码经验,第一反映应该是这些地方调用了add_lunch_combo
aosp@ubuntu:~/android5.1$ source build/envsetup.sh
including device/lge/hammerhead/vendorsetup.sh
including device/lge/mako/vendorsetup.sh
including device/samsung/manta/vendorsetup.sh
including device/generic/mini-emulator-arm64/vendorsetup.sh
including device/generic/mini-emulator-x86_64/vendorsetup.sh
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
including device/generic/mini-emulator-x86/vendorsetup.sh
including device/generic/mini-emulator-mips/vendorsetup.sh
including device/moto/shamu/vendorsetup.sh
including device/asus/flo/vendorsetup.sh
including device/asus/tilapia/vendorsetup.sh
including device/asus/deb/vendorsetup.sh
including device/asus/grouper/vendorsetup.sh
including device/asus/fugu/vendorsetup.sh
including device/htc/flounder/vendorsetup.sh
including sdk/bash_completion/adb.bash
那这些又是在哪里include的呢?
# Execute the contents of any vendorsetup.sh files we can find.
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null` \
`test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null`
do
echo "including $f"
. $f
done
unset f
在我们的device目录下第一层
最深不超过4层,找到vendorsetup.sh,以及vendor目录下,一般厂商定义的会在vendor目录下。但是我们平时开发一般不遵守的,因为打开文件的时候真的麻烦。打开两个地方。
到这里,我们随便找一个vendorsetup.sh
文件查看一下。
比如说:
including device/lge/hammerhead/vendorsetup.sh
我们就发现
add_lunch_combo aosp_hammerhead-userdebug
卧草,这不就是跟前面一样,okay,这样子就添加进列表里去了。那添加进去只是个名字呀,这个名字怎么样起作用呢?
我们双回到最开始lunch的命令下,看看我们选择了5以后,干了啥。
function lunch()
{
local answer
....省略代码,目标列表已经输出,answer值也得到了....
# 定义一个选项变量
local selection=
# 如果答案长度为0,那默认是aosp_arm-eng
if [ -z "$answer" ]
then
selection=aosp_arm-eng
# 如果有答案,就对答案进行检查
# 如果输入的是数字,在列表里找到,转成名字串
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
# 如果小于列表的长度,说明在范围内
if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
then
# 选择对应下标的名字串
selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
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
# 到这里selection是有值的了
# 把环境中的TARGET_BUILD_APPS设置为空
export TARGET_BUILD_APPS=
# 对名字串里的-xxx替换掉
# aosp_x86-eng变成aosp_x86
local product=$(echo -n $selection | sed -e "s/-.*$//")
# 检查产品是否有的,如果返回值不为0,说明产品不对,也就是选择的/输入的不对。
check_product $product
if [ $? -ne 0 ]
then
echo
echo "** Don't have a product spec for: '$product'"
echo "** Do you have the right repo manifest?"
product=
fi
....省略代码....
}
到这里我们先去看一个分支,检查产品,看看检查产品干了啥
# check to see if the supplied product is one we can build
function check_product()
{
# 获取到工作目录/home/aosp/android5.1
T=$(gettop)
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
TARGET_PRODUCT=$1 \
TARGET_BUILD_VARIANT= \
TARGET_BUILD_TYPE= \
TARGET_BUILD_APPS= \
get_build_var TARGET_DEVICE > /dev/null
# hide successful answers, but allow the errors to show
}
设置TARGET_PRODUCT变量值,$1就是我们前面传进来的第一个参数$product
然后调用get_build_var
# Get the exact value of a build variable.
function get_build_var()
{
T=$(gettop)
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
# 设置变量,载入config.mk文件,mk文件由make去解析
(\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
command make --no-print-directory -f build/core/config.mk dumpvar-$1)
}
也没干啥,设置变量,执行config.mk
我们回到lunch上继续看
function lunch()
{
local answer
if [ "$1" ] ; then
answer=$1
else
print_lunch_menu
echo -n "Which would you like? [aosp_arm-eng] "
read answer
fi
local selection=
if [ -z "$answer" ]
then
selection=aosp_arm-eng
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
then
selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
fi
elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
then
selection=$answer
fi
if [ -z "$selection" ]
then
echo
echo "Invalid lunch combo: $answer"
return 1
fi
export TARGET_BUILD_APPS=
local product=$(echo -n $selection | sed -e "s/-.*$//")
# 如果返回值不为0,那么就输出提示信息
check_product $product
if [ $? -ne 0 ]
then
echo
echo "** Don't have a product spec for: '$product'"
echo "** Do you have the right repo manifest?"
product=
fi
# aosp_x86-eng变成eng了,也就是获取到构建类型是user版本,还是userdebug版本,又或者debug版本
# 详情请看下方的构建类型说明
local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
# 检查是不是对的
check_variant $variant
if [ $? -ne 0 ]
then
echo
echo "** Invalid variant: '$variant'"
echo "** Must be one of ${VARIANT_CHOICES[@]}"
variant=
fi
...省略代码...
}
关于构建类型的说明:
check_variant $variant
VARIANT_CHOICES=(user userdebug eng)
# check to see if the supplied variant is valid
function check_variant()
{
for v in ${VARIANT_CHOICES[@]}
do
if [ "$v" = "$1" ]
then
return 0
fi
done
return 1
}
可以看出,只有三种构建类型。
okay,继续往下去看看
function lunch()
{
...省略代码...
# 再对产品和构建类型进行检查
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
echo
# 设置各种环境变量
set_stuff_for_environment
# 输出配置信息
printconfig
}
set_stuff_for_environment,这里面又分了几个分支去做其他事情
- settitle 设置标题
- set_java_home 设置java的路径
- setpaths 设置环境变量
- set_sequence_number 设置序号
function set_stuff_for_environment()
{
settitle
set_java_home
setpaths
set_sequence_number
export ANDROID_BUILD_TOP=$(gettop)
# With this environment variable new GCC can apply colors to warnings/errors
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
}
printconfig 输出配置信息
function printconfig()
{
T=$(gettop)
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
get_build_var report_config
}
下面我们对比一下,lunch前后的配置信息
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
TARGET_ARCH_VARIANT=armv7-a
TARGET_CPU_VARIANT=generic
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.4.0-90-generic-x86_64-with-Ubuntu-18.04-bionic
HOST_BUILD_TYPE=release
BUILD_ID=LMY47D
OUT_DIR=out
============================================
lunch 5. aosp_x86-eng 之后
============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=5.1
TARGET_PRODUCT=aosp_x86
TARGET_BUILD_VARIANT=eng
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=x86
TARGET_ARCH_VARIANT=x86
TARGET_CPU_VARIANT=
TARGET_2ND_ARCH=
TARGET_2ND_ARCH_VARIANT=
TARGET_2ND_CPU_VARIANT=
HOST_ARCH=x86_64
HOST_OS=linux
HOST_OS_EXTRA=Linux-5.4.0-90-generic-x86_64-with-Ubuntu-18.04-bionic
HOST_BUILD_TYPE=release
BUILD_ID=LMY47D
OUT_DIR=out
============================================
环境变量前后的区别
lunch之前的环境变量内容
aosp@ubuntu:~$ export
declare -x CLUTTER_IM_MODULE="xim"
declare -x COLORTERM="truecolor"
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x DESKTOP_AUTOSTART_ID="10d28aafa23347d7f3163801459414654300000034500007"
declare -x DESKTOP_SESSION="ubuntu"
declare -x DISPLAY=":0"
declare -x GDMSESSION="ubuntu"
declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated"
declare -x GNOME_SHELL_SESSION_MODE="ubuntu"
declare -x GNOME_TERMINAL_SCREEN="/org/gnome/Terminal/screen/c3085c45_2cae_4799_afb9_524095904c0b"
declare -x GNOME_TERMINAL_SERVICE=":1.88"
declare -x GPG_AGENT_INFO="/run/user/1000/gnupg/S.gpg-agent:0:1"
declare -x GTK_IM_MODULE="ibus"
declare -x GTK_MODULES="gail:atk-bridge"
declare -x HOME="/home/aosp"
declare -x IM_CONFIG_PHASE="2"
declare -x JAVA_HOME="/home/aosp/devTools/jdk1.7.0_80"
declare -x LANG="en_US.UTF-8"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LIBVIRT_DEFAULT_URI="qemu:///system"
declare -x LOGNAME="aosp"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x OLDPWD
declare -x PATH="/home/aosp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/aosp/devTools/jdk1.7.0_80/bin"
declare -x PWD="/home/aosp"
declare -x QT4_IM_MODULE="xim"
declare -x QT_ACCESSIBILITY="1"
declare -x QT_IM_MODULE="ibus"
declare -x REPO_URL="https://mirrors.tuna.tsinghua.edu.cn/git/git-repo"
declare -x SESSION_MANAGER="local/ubuntu:@/tmp/.ICE-unix/3450,unix/ubuntu:/tmp/.ICE-unix/3450"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_PID="3552"
declare -x SSH_AUTH_SOCK="/run/user/1000/keyring/ssh"
declare -x TERM="xterm-256color"
declare -x TEXTDOMAIN="im-config"
declare -x TEXTDOMAINDIR="/usr/share/locale/"
declare -x USER="aosp"
declare -x USERNAME="aosp"
declare -x VTE_VERSION="5202"
declare -x WINDOWPATH="2"
declare -x XAUTHORITY="/run/user/1000/gdm/Xauthority"
declare -x XDG_CONFIG_DIRS="/etc/xdg/xdg-ubuntu:/etc/xdg"
declare -x XDG_CURRENT_DESKTOP="ubuntu:GNOME"
declare -x XDG_DATA_DIRS="/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop"
declare -x XDG_MENU_PREFIX="gnome-"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SEAT="seat0"
declare -x XDG_SESSION_DESKTOP="ubuntu"
declare -x XDG_SESSION_ID="2"
declare -x XDG_SESSION_TYPE="x11"
declare -x XDG_VTNR="2"
declare -x XMODIFIERS="@im=ibus"
aosp@ubuntu:~$
lunch之后
aosp@ubuntu:~/android5.1$ export
declare -x ANDROID_BUILD_PATHS="/home/aosp/android5.1/out/host/linux-x86/bin:/home/aosp/android5.1/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/bin:/home/aosp/android5.1/prebuilts/gcc/linux-x86/:/home/aosp/android5.1/development/scripts:/home/aosp/android5.1/prebuilts/devtools/tools:/home/aosp/android5.1/prebuilts/android-emulator/linux-x86_64:"
declare -x ANDROID_BUILD_TOP="/home/aosp/android5.1"
declare -x ANDROID_DEV_SCRIPTS="/home/aosp/android5.1/development/scripts:/home/aosp/android5.1/prebuilts/devtools/tools"
declare -x ANDROID_EMULATOR_PREBUILTS="/home/aosp/android5.1/prebuilts/android-emulator/linux-x86_64"
declare -x ANDROID_HOST_OUT="/home/aosp/android5.1/out/host/linux-x86"
declare -x ANDROID_JAVA_TOOLCHAIN="/home/aosp/devTools/jdk1.7.0_80/bin"
declare -x ANDROID_PRE_BUILD_PATHS="/home/aosp/devTools/jdk1.7.0_80/bin:"
declare -x ANDROID_PRODUCT_OUT="/home/aosp/android5.1/out/target/product/generic_x86"
declare -x ANDROID_TOOLCHAIN="/home/aosp/android5.1/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/bin"
declare -x ANDROID_TOOLCHAIN_2ND_ARCH="/home/aosp/android5.1/prebuilts/gcc/linux-x86/"
declare -x BUILD_ENV_SEQUENCE_NUMBER="10"
declare -x CLUTTER_IM_MODULE="xim"
declare -x COLORTERM="truecolor"
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x DESKTOP_AUTOSTART_ID="10d28aafa23347d7f3163801459414654300000034500007"
declare -x DESKTOP_SESSION="ubuntu"
declare -x DISPLAY=":0"
declare -x GCC_COLORS="error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
declare -x GDMSESSION="ubuntu"
declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated"
declare -x GNOME_SHELL_SESSION_MODE="ubuntu"
declare -x GNOME_TERMINAL_SCREEN="/org/gnome/Terminal/screen/c3085c45_2cae_4799_afb9_524095904c0b"
declare -x GNOME_TERMINAL_SERVICE=":1.88"
declare -x GPG_AGENT_INFO="/run/user/1000/gnupg/S.gpg-agent:0:1"
declare -x GTK_IM_MODULE="ibus"
declare -x GTK_MODULES="gail:atk-bridge"
declare -x HOME="/home/aosp"
declare -x IM_CONFIG_PHASE="2"
declare -x JAVA_HOME="/home/aosp/devTools/jdk1.7.0_80"
declare -x LANG="en_US.UTF-8"
declare -x LC_ALL="C"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LIBVIRT_DEFAULT_URI="qemu:///system"
declare -x LOGNAME="aosp"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x OLDPWD="/home/aosp"
declare -x OUT="/home/aosp/android5.1/out/target/product/generic_x86"
declare -x PATH="/home/aosp/devTools/jdk1.7.0_80/bin:/home/aosp/android5.1/out/host/linux-x86/bin:/home/aosp/android5.1/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8/bin:/home/aosp/android5.1/prebuilts/gcc/linux-x86/:/home/aosp/android5.1/development/scripts:/home/aosp/android5.1/prebuilts/devtools/tools:/home/aosp/android5.1/prebuilts/android-emulator/linux-x86_64:/home/aosp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/aosp/devTools/jdk1.7.0_80/bin"
declare -x PROMPT_COMMAND="echo -ne \"\\033]0;[x86-aosp_x86-eng] aosp@ubuntu: /home/aosp/android5.1\\007\""
declare -x PWD="/home/aosp/android5.1"
declare -x QT4_IM_MODULE="xim"
declare -x QT_ACCESSIBILITY="1"
declare -x QT_IM_MODULE="ibus"
declare -x REPO_URL="https://mirrors.tuna.tsinghua.edu.cn/git/git-repo"
declare -x SESSION_MANAGER="local/ubuntu:@/tmp/.ICE-unix/3450,unix/ubuntu:/tmp/.ICE-unix/3450"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_PID="3552"
declare -x SSH_AUTH_SOCK="/run/user/1000/keyring/ssh"
declare -x TARGET_BUILD_APPS=""
declare -x TARGET_BUILD_TYPE="release"
declare -x TARGET_BUILD_VARIANT="eng"
declare -x TARGET_GCC_VERSION="4.8"
declare -x TARGET_PRODUCT="aosp_x86"
declare -x TERM="xterm-256color"
declare -x TEXTDOMAIN="im-config"
declare -x TEXTDOMAINDIR="/usr/share/locale/"
declare -x USER="aosp"
declare -x USERNAME="aosp"
declare -x VTE_VERSION="5202"
declare -x WINDOWPATH="2"
declare -x XAUTHORITY="/run/user/1000/gdm/Xauthority"
declare -x XDG_CONFIG_DIRS="/etc/xdg/xdg-ubuntu:/etc/xdg"
declare -x XDG_CURRENT_DESKTOP="ubuntu:GNOME"
declare -x XDG_DATA_DIRS="/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop"
declare -x XDG_MENU_PREFIX="gnome-"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SEAT="seat0"
declare -x XDG_SESSION_DESKTOP="ubuntu"
declare -x XDG_SESSION_ID="2"
declare -x XDG_SESSION_TYPE="x11"
declare -x XDG_VTNR="2"
declare -x XMODIFIERS="@im=ibus"
注意观察ANDROID开关的,到这里我们就看完了lunch的过程了
接下来我们要创建属于我们自己的产品。
make 开始编译
我们lunch完选择构建目标,然后就make -j8
,或者输出log的方式编译make -j8 2>&1 | tee build.log
进行编译
那么make的时候到底是干了啥,入口是哪里呢?
首先,我们在源码根目录下make,这里面有一个文件叫做Makefile
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###
它就include了build/core/main.mk
,可以理解为调用这个文件,这个就是我们系统编译的入口了。
这里可以看到我们的又include其他文件了
这里面有include和-include这两个的区别是啥呢?-include的话如果这个文件不存在,也会继续往下执行,如果是include就会提示no rule to make target
以上我们可以大概地得到这样一个关系图
在整个编译系统中,Android的makefile文件主要分成三类
- 编译框架,也就是我们build/core目录下的mk文件,它其实就是控制我们编译的一个框架了,也就是控制编译的流程。
- 产品定义,一般是在device目录下,或者vendor下。这就是为什么在创建产品之前和大家一直来了解编译流程,了解这些才知道如何去添加自己的产品。
- 产品相关的,主板相关的
- Android.mk,这个前面已经和大家接触过了,我们编译jar包,编译可执行文件,编译apk之类的。
由此我们知道,编译框架,就会去include产品的,各个模块里的Android.mk文件
产品的在哪里添加呢?
这个路线是这样子的:
main.mk--->config.mk--->envsetup.mk---->product_config.mk
在product.mk里,就会去查找device目录下,vendor目录下,target目录下的AndroidProducts.mk文件
define _find-android-products-files
$(shell test -d device && find device -maxdepth 6 -name AndroidProducts.mk) \
$(shell test -d vendor && find vendor -maxdepth 6 -name AndroidProducts.mk) \
$(SRC_TARGET_DIR)/product/AndroidProducts.mk
endef
_find-android-products-files
就是所找到的AndroidProducts.mk文件列表了
然后值就到了get-all-product-makefiles
define get-product-makefiles
$(sort \
$(foreach f,$(1), \
$(eval PRODUCT_MAKEFILES :=) \
$(eval LOCAL_DIR := $(patsubst %/,%,$(dir $(f)))) \
$(eval include $(f)) \
$(PRODUCT_MAKEFILES) \
) \
$(eval PRODUCT_MAKEFILES :=) \
$(eval LOCAL_DIR :=) \
)
endef
#
# Returns the sorted concatenation of all PRODUCT_MAKEFILES
# variables set in all AndroidProducts.mk files.
# $(call ) isn't necessary.
#
define get-all-product-makefiles
$(call get-product-makefiles,$(_find-android-products-files))
endef
再回到product_config.mk上,给到了all_product_configs
,TARGET_BUILD_APPS这个值为空的,所以走的是else的逻辑,也就是前面我们load的列表
ifneq ($(strip $(TARGET_BUILD_APPS)),)
# An unbundled app build needs only the core product makefiles.
all_product_configs := $(call get-product-makefiles,\
$(SRC_TARGET_DIR)/product/AndroidProducts.mk)
else
# Read in all of the product definitions specified by the AndroidProducts.mk
# files in the tree.
all_product_configs := $(get-all-product-makefiles)
endif
all_product_configs
这个在哪里处理呢?同样在product_config.mk里
current_product_makefile :=
all_product_makefiles :=
$(foreach f, $(all_product_configs),\
$(eval _cpm_words := $(subst :,$(space),$(f)))\
$(eval _cpm_word1 := $(word 1,$(_cpm_words)))\
$(eval _cpm_word2 := $(word 2,$(_cpm_words)))\
$(if $(_cpm_word2),\
$(eval all_product_makefiles += $(_cpm_word2))\
$(if $(filter $(TARGET_PRODUCT),$(_cpm_word1)),\
$(eval current_product_makefile += $(_cpm_word2)),),\
$(eval all_product_makefiles += $(f))\
$(if $(filter $(TARGET_PRODUCT),$(basename $(notdir $(f)))),\
$(eval current_product_makefile += $(f)),)))
_cpm_words :=
_cpm_word1 :=
_cpm_word2 :=
current_product_makefile := $(strip $(current_product_makefile))
我们可以输出一下,就知道这个当前的current_product_makefile了
$(error $(current_product_makefile))
输出了log
build/core/product_config.mk:216: *** build/target/product/aosp_x86.mk. Stop.
其实后面载入的是build/target/product/aosp_x86.mk
当我们选择其他编译项的时候呢? 如说我选择19. aosp_grouper-userdebug
那么它的产品makefile是啥呢? 输出的Log就是这个了
build/core/product_config.mk:215: *** device/asus/grouper/aosp_grouper.mk. Stop.
可以看到,前面我们的aosp_x86是在build/target目录下的,而后面这个是在device目录下的,现在你知道为什么扫描会扫描build/target目录,会扫描device目录以及vendor目录了吧里的AndroidProducts.mk文件。
品牌的创建
那么我们创建自己的产品是不是就有头绪了呢?以iphone为例子
第一步:有自己的一个vendorsetup.sh,里面add_lunch_combo iphone
,这样子,我们在lunch的时候,就会有我们自己的选项了,那么怎么样才能让它编译我们的主板和产品配置呢?
第二步:在device目录下,或者在vendor目录下,或者在target目录下,通常我们在device目录下去创建属于自己的文件夹,我们这个名字就叫iphone吧,里面有内容,我们是不是可以去复制x86的呀。因为我们是模拟器,如果是芯片商给你提供的,其实已经创建好的了,你去复制一份即可,然后修改成自己的。
第三步:尝试编译,如果通过了,再去修改产品配置,我们是模拟器,主板配置基本上没有修改的。
实际来干吧,先来个文件夹
然后复制一个vendorsetup.sh过来,里面改成:
add_lunch_combo iphone-userdebug
保存,然后重新载入一下evnsetup.sh
这样子就有了我们这个产品了,那么怎么样才能让它找到我们的配置呢?还是拷贝,我们可以参考一下x86的,具体内容请看视频,或者看资料里的最后结果。
由品牌创建产品
完成了前面的工作,我们已经完成了iphone的品牌创建了。在实际开发中,是不需要自己创建这个的,一般来说,芯片厂商给到你的一套代码,已经包含了。你自己拷贝一份,去修改即可。
接下来我们创建iphone12这个产品