android 编译系统流程简介




一、Android编译步骤:

   android 编译系统流程简介_第1张图片

二、初始化编译环境--source build/envsetup.sh

  在build/envsetup.sh中主要完成了三件事。

   android 编译系统流程简介_第2张图片

  添加编译目标的代码如下:

  1. <font color="rgb(0, 0, 0)"><font style="background-color:rgb(250, 247, 239)"><font face="微软雅黑, PTSans, Arial, sans-serif"><font style="font-size: 16px">for f in `/bin/ls vendor/*/vendorsetup.sh vendor/*/*/vendorsetup.sh device/*/*/vendorsetup.sh 2> /dev/null`
  2. do
  3.     echo "including $f"
  4.     . $f
  5. done
  6. unset f</font></font></font></font>
复制代码
三、选择编译目标--lunch  通过lunch选择编译目标,函数定义如下:
  1. function lunch(){
  2.     local answer  
  3.   //如果调用lunch时带参数就表示手动指定编译目标,否则打印选择编译目标的菜单
  4.     if [ "$1" ] ; then
  5.         answer=$1
  6.     else
  7.         print_lunch_menu
  8.         echo -n "Which would you like? [full-eng] "
  9.         read answer
  10.     fi

  11.     local selection=

  12.   //如果没有编译目标默认为full-eng,否则如果answer是数字就将其转换为对应的字符串表示
  13.     if [ -z "$answer" ]
  14.     then
  15.         selection=full-eng
  16.     elif (echo -n $answer | grep -q -e "^[0-9][0-9]*[        DISCUZ_CODE_1        ]quot;)
  17.     then
  18.         if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
  19.         then
  20.             selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
  21.         fi
  22.     elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*[        DISCUZ_CODE_1        ]quot;)
  23.     then
  24.         selection=$answer
  25.     fi

  26.   //如果表示编译目标的字符串是空的表示非法选择,错误返回
  27.     if [ -z "$selection" ]
  28.     then
  29.         echo
  30.         echo "Invalid lunch combo: $answer"
  31.         return 1
  32.     fi

  33.     export TARGET_BUILD_APPS=

  34.    //检测选择的product是否合法(只要在相应目录新建vendorsetup.sh并add_lunch_combo就可在lunch menu中显示相应项,但如果不配置product相关信息就会Invalid)
  35.   local product=$(echo -n $selection | sed -e "s/-.*$//")
  36.     check_product $product
  37.     if [ $? -ne 0 ]
  38.     then
  39.         echo
  40.         echo "** Don't have a product spec for: '$product'"
  41.         echo "** Do you have the right repo manifest?"
  42.         product=
  43.     fi

  44.   //从selection解析出product,variant
  45.     local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
  46.     check_variant $variant
  47.     if [ $? -ne 0 ]
  48.     then
  49.         echo
  50.         echo "** Invalid variant: '$variant'"
  51.         echo "** Must be one of ${VARIANT_CHOICES[@]}"
  52.         variant=
  53.     fi

  54.     if [ -z "$product" -o -z "$variant" ]
  55.     then
  56.         echo
  57.         return 1
  58.     fi

  59.   //导出TARGET_PRODECT,TARGET_BUILD_VARIANT与TARGET_BUILD_TYPE,比如若选择的是full-eng,那么TARGET_PRODUCT=full,TARGET_BUILD_VARIANT=eng
  60.     export TARGET_PRODUCT=$product
  61.     export TARGET_BUILD_VARIANT=$variant
  62.     export TARGET_BUILD_TYPE=release

  63.     echo

  64.     set_stuff_for_environment
  65.     printconfig
  66. }
复制代码
四、编译--make -j8  要make肯定有Makefile,Android根目录的Makefile只是简单地include进来了一个文件:
  1. ### DO NOT EDIT THIS FILE ###  
  2. include build/core/main.mk  
  3. ### DO NOT EDIT THIS FILE ###  
复制代码
而build/core/main.mk就比较复杂了,以下是main.mk的结构图:android 编译系统流程简介_第3张图片  
在main.mk中首先定义了默认编译目标并做版本检查,然后include config.mk。
  在config.mk中定义了在Android.mk中编译目标时会用到的常量
  1. CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
  2. BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
  3. BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
  4. BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
  5. BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
  6. BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
  7. BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
  8. BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
  9. BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
  10. BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
  11. BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk
  12. BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
  13. BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
  14. BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
  15. BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
  16. BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
  17. BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
  18. BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
  19. BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
  20. BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk
  21. BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk
复制代码
然后include进来了/build/core/envsetup.sh,在envsetup.sh中定义了HOST_OS,OUT_DIR等环境变量,并通过include product_config.mk检索所有Product,并做有效性检查,然后根据lunch时选择的Product设置TARGET_DEVICE。
  然后在envsetup.sh中根据TARGET_DEVICE查找BoardConfig.mk文件进行Board相关配置,查找KERNEL_HEADER,配置编译工具链。
  在definitions.mk中定义了all_makefiles_under等用来检索文件的函数。
  根据TARGET_BUILD_VARIANT设置ro.secure等系统属性,设定tags_to_install等变量。
  接下来通过
  1. subdir_makefiles := \
  2.     $(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)

  3. include $(subdir_makefiles)
复制代码
找到所有子目录下的Android.mk文件并include进来,这样在Android.mk定义的LOCAL_PACKAGE_NAME与include $(BUILD_PACKAGE)就可以将相应的Android.mk中定义的目标包含进编译模块中,在config.mk中有如下定义:
  1. BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
复制代码
而package.mk又包含base_rules.mk将LOCAL_MODULE添加到ALL_MODULES中。
  post_clean.mk是跟Resource Overlay相关,使们们不需要修改framework中原来的资源文件就可以定义framework-res.apk中的资源。
  接下来include build/core/Makefile文件,定义bootimage,systemimage等信赖目标,然后通过make编译droid(默认)目标就可以编译系统了。
  Android采用检索所有子目录中的Android.mk将所有要编译的模块收集起来的方式编译系统,而不是进入到每个子目录执行make,这样就方便了我们添加自己的模块。 

你可能感兴趣的:(android 编译系统流程简介)