潜心静气。。慢慢出成果
全部博文(37)
分类: Android平台
2016-10-18 15:29:23
从拿到代码执行source build/envsetup.sh到镜像文件下载到板级跑起来,期间代码编译过程和各文件生成过程分析:
Source build/envsetup.sh
首先envsetup.sh里有大量的函数,最终要加入当前终端的PATH中去,函数编程shell命令,便于执行build。
函数格式如下:function _lunch() 可直接在shell下执行lunch。
最终会把各个硬件厂商的vendersetup.sh都加入到当前环境中。
具体执行如下:find各个厂商的vendorsetup.sh,include到当前环境。
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
同时把lunch的菜单选项加入到
LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)。
add_lunch_combo aosp_arm-eng
同时find 硬件厂商的vendorsetup.sh中的也会把这些环境变量中LUNCH_MENU_CHOICES
使用lunch时会把这些可选择参数打印出来。
选择完17后使用这个参数来配置文件,eng user userdebug在环境配置上具体的差异在于内核是否打印,如下。
full_land6735m_35gc_l1.mk 由AndroidProducts.mk调用,而AndroidProducts.mk被加入到环境参数PRODUCT_MAKEFILES中。
AndroidProducts.mk被加载到配置环境中的简单分析:
在envsetup.sh的lunch函数中会判断当前的变量赋值是否为空,如果不为空则默认选择,为空调用check_board
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/-.*$//")
check_product $product
Check_product调用get_build_var
get_build_var TARGET_DEVICE > /dev/null
get_build_var寻找到build/core/config.mk
(\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
command make --no-print-directory -f build/core/config.mk dumpvar-$1)
进入到config.mk查看是如何调用到目标文件的。
在config.mk调用了envsetup.mk
include $(BUILD_SYSTEM)/envsetup.mk
在envsetup.mk调用product_config.mk
include $(BUILD_SYSTEM)/product_config.mk
查看product_config.mk的内容发现把所有的配置文件读取到环境中。
full_land6735m_35gc_l1.mk内容如下:
including sdk/bash_completion/adb.bash
在sdk/bash_completion目录下的adb.bash文件也会加载到当前终端来,它是用来实现adb命令的bash completion功能的。也就是说,加载了该文件之后,我们在运行adb相关的命令的时候,通过按tab键就可以帮助我们自动完成命令的输入。
Lunch的作用:lunch命令帮我们设置好了很多环境变量。通过设置这些环境变量,就配置好了Android编译环境。
lunch命令设置好了TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_BUILD_TYPE和TARGET_BUILD_APPS等。
打包过程:
我们在使用 m mm mmm时其实都是对make指令的封装。m mm mmm使用时都是如mm。
函数mm首先是判断当前目录是否就是Android源码根目录,即当前目录下是否存在一个build/core/envsetup.mk文件和一个Makefile文件。如果是的话,就将命令mm当作是一个普通的make命令来执行。否则的话,就调用函数findmakefile从当前目录开始一直往上寻找是否存在一个Android.mk文件。如果在寻找的过程中,发现了一个Android.mk文件,那么就获得它的绝对路径,并且停止上述寻找过程。
PL LK KL的编译则是Makefile中将其Makefile include到编译规则中,执行编译时直接回到各自源码目录下执行编译。
在打包boot.imag system.img recovery.img userdata.img编译规则则是由各级Android.mk所依赖。
这个图截至罗升阳老师的博客。
build/core/main.mk是Android编译系统的入口文件,它通过加载其它的mk文件来对Android源码中的各个模块进行编译,以及将编译出来的文件打包成各种镜像文件。
build/core/Makefile主要就是用来打包各种Android系统镜像文件的,当然它也是通过make规则来执行各种Android系统镜像文件打包命令的。每一个Android镜像文件都对应有一个make伪目标。例如,在build/core/main.mk文件中,就定义了三个make伪目标ramdisk、userdataimage和bootimage。Build就是打包镜像,和环境配置。Device则是当前板级project的配置。
在main.mk中有如下目标,在top目录执行时,最终回到main.mk里,然后执行同目录下的Makefile编译镜像。
通常,如果我们在Android源码中修改了某一个模块,并且这个模块不被其它模块依赖,那么对这个模块进行编译之后,就可以简单地执行make systemimg-nodeps来重新打包system.img。但是,如果我们修改的模块会被其它模块引用,例如,我们修改了Android系统的核心模块framework.jar和services.jar,那么就需要执行make systemimg来更新所有依赖于framework.jar和services.jar的模块,那么最后得到的system.img才是正确的镜像。否则的话,会导致Android系统启动失败。
http://blog.csdn.net/luoshengyang/article/details/20501657/
在文件打包选项中,如何才能知道那些需要打包,那些不需要打包呢?经过阅读源代码的配置文件才知道原来在build/core/product.mk中定义了很多规则如下:
_product_var_list := \
PRODUCT_NAME \
PRODUCT_MODEL \
PRODUCT_LOCALES \
PRODUCT_AAPT_CONFIG \
PRODUCT_AAPT_PREF_CONFIG \
PRODUCT_AAPT_PREBUILT_DPI \
PRODUCT_PACKAGES \
PRODUCT_PACKAGES_DEBUG \
PRODUCT_PACKAGES_ENG \
PRODUCT_PACKAGES_TESTS \
PRODUCT_DEVICE \
PRODUCT_MANUFACTURER \
PRODUCT_BRAND \
PRODUCT_PROPERTY_OVERRIDES \
PRODUCT_DEFAULT_PROPERTY_OVERRIDES \
PRODUCT_CHARACTERISTICS \
PRODUCT_COPY_FILES \
PRODUCT_OTA_PUBLIC_KEYS \
PRODUCT_EXTRA_RECOVERY_KEYS \
PRODUCT_PACKAGE_OVERLAYS \
DEVICE_PACKAGE_OVERLAYS \
PRODUCT_TAGS \
PRODUCT_SDK_ATREE_FILES \
PRODUCT_SDK_ADDON_NAME \
PRODUCT_SDK_ADDON_COPY_FILES \
PRODUCT_SDK_ADDON_COPY_MODULES \
PRODUCT_SDK_ADDON_DOC_MODULES \
PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP \
PRODUCT_DEFAULT_WIFI_CHANNELS \
PRODUCT_DEFAULT_DEV_CERTIFICATE \
PRODUCT_RESTRICT_VENDOR_FILES \
PRODUCT_VENDOR_KERNEL_HEADERS \
PRODUCT_FACTORY_RAMDISK_MODULES \
PRODUCT_FACTORY_BUNDLE_MODULES \
PRODUCT_RUNTIMES \
PRODUCT_BOOT_JARS \
PRODUCT_SUPPORTS_VERITY \
PRODUCT_OEM_PROPERTIES \
PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
PRODUCT_SYSTEM_SERVER_JARS \
PRODUCT_VERITY_SIGNING_KEY \
PRODUCT_SYSTEM_VERITY_PARTITION \
PRODUCT_VENDOR_VERITY_PARTITION \
PRODUCT_DEX_PREOPT_IMAGE_IN_DATA \
PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
PRODUCT_DEX_PREOPT_BOOT_FLAGS \
这些规则中就是PRODUCT为前缀,制定着编译源代码目录的编译,其中PRODUCT_PACKAGES决定着那些文件编译,PRODUCT_COPY_FILES决定着那些文件拷贝。
这些选项都是定义在devices/bitland/project/devices.mk中下或者/device/mediatek/devices.mk
阅读devices.mk发现其实很多宏定义开关。
ifeq ($(strip $(MTK_IRTX_SUPPORT)),yes)
PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.consumerir.xml:system/etc/permissions/android.hardware.consumerir.xml
PRODUCT_PACKAGES += consumerir.mt6735
PRODUCT_PACKAGES += consumerir.mt6735m
PRODUCT_PACKAGES += consumerir.mt6753
Endif
这些开关的定义在./devices/bitland/project/project_config.mk
终于画上一个完整的执行逻辑了。
以上仅是system.img boot.img userdata.img的打包。Mediatek中的pl lk kl的编译完全依靠自己的Makefile文件,这些跟Linux底层有关系,不再分析。