android系統編譯流程

一、source build/envsetup.sh

1、定義函數
如 lunch croot mm mmm mma mmma cgrep make等

2、VARIANT_CHOICES=(user userdebug eng) 編譯選項值

3、unset LUNCH_MENU_CHOICES

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

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_lunch_combo後面的參數加到LUNCH_MENU_CHOICES這個值裏面
}

4、complete -F _lunch lunch 定義lunch命令的Tab補全函數

5、檢查shell是否爲bash
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

6、查找並執行device vendor product目錄下面的vendorsetup.sh
for f in `test -d device && find -L device -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d vendor && find -L vendor -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort` \
         `test -d product && find -L product -maxdepth 4 -name 'vendorsetup.sh' 2> /dev/null | sort`
do
    echo "including $f"
    . $f
done

including device/generic/car/vendorsetup.sh
    add_lunch_combo aosp_car_arm-userdebug
    add_lunch_combo aosp_car_arm64-userdebug
    add_lunch_combo aosp_car_x86-userdebug
    add_lunch_combo aosp_car_x86_64-userdebug
including device/generic/mini-emulator-arm64/vendorsetup.sh
    add_lunch_combo mini_emulator_arm64-userdebug
including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
    add_lunch_combo m_e_arm-userdebug
including device/generic/mini-emulator-x86_64/vendorsetup.sh
    add_lunch_combo mini_emulator_x86_64-userdebug
including device/generic/mini-emulator-x86/vendorsetup.sh
    add_lunch_combo mini_emulator_x86-userdebug
including device/generic/uml/vendorsetup.sh
    add_lunch_combo uml-userdebug
including device/google/muskie/vendorsetup.sh
    add_lunch_combo aosp_walleye-userdebug
    add_lunch_combo aosp_walleye_test-userdebug
including device/google/taimen/vendorsetup.sh
    add_lunch_combo aosp_taimen-userdebug
including device/qcom/common/vendorsetup.sh
    add_lunch_combo xxx8974-userdebug
    add_lunch_combo xxx8610-userdebug
    add_lunch_combo xxx8226-userdebug
    add_lunch_combo apq8084-userdebug
    add_lunch_combo mpq8092-userdebug
    add_lunch_combo xxx_bronze-userdebug
    add_lunch_combo xxx8916_32-userdebug
    add_lunch_combo xxx8916_32_512-userdebug
    add_lunch_combo xxx8916_32_k64-userdebug
    add_lunch_combo xxx8916_64-userdebug
    add_lunch_combo xxx8994-userdebug
    add_lunch_combo xxx8996-userdebug
    add_lunch_combo xxx8909-userdebug
    add_lunch_combo xxx8909go-userdebug
    add_lunch_combo xxx8909_512-userdebug
    add_lunch_combo xxx8909_512go-userdebug
    add_lunch_combo xxx8992-userdebug
    add_lunch_combo xxx8952_64-userdebug
    add_lunch_combo xxx8952_32-userdebug
    add_lunch_combo xxx8937_32-userdebug
    add_lunch_combo xxx8937_32go-userdebug
    add_lunch_combo xxx8937_64-userdebug
    add_lunch_combo xxx8953_32-userdebug
    add_lunch_combo xxx8953_64-userdebug
    add_lunch_combo xxx8998-userdebug
    add_lunch_combo xxx8998_32-userdebug
    add_lunch_combo sdm660_64-userdebug
    add_lunch_combo sdm660_32-userdebug
    add_lunch_combo sdm845-userdebug
    add_lunch_combo apq8098_latv-userdebug
    add_lunch_combo sdm710-userdebug
    add_lunch_combo xxxnile-userdebug
    add_lunch_combo xxxnile_au-userdebug
    add_lunch_combo xxxnile_gvmq-userdebug
    add_lunch_combo qcs605-userdebug
    add_lunch_combo sm6150-userdebug
    add_lunch_combo sm6150_au-userdebug
    add_lunch_combo sm6150_au_gvmq-userdebug
    add_lunch_combo trinket-userdebug
    add_lunch_combo sdmshrike_au-userdebug
including device/qcom/qssi/vendorsetup.sh
    add_lunch_combo qssi-userdebug
including vendor/qcom/opensource/core-utils/vendorsetup.sh
    export QTI_BUILDTOOLS_DIR=$(dirname ${BASH_SOURCE[0]})
including vendor/qcom/proprietary/common/vendorsetup.sh
    export QCPATH="vendor/qcom/proprietary"
    export QCPATH_COMMONSYS="${QCPATH}/commonsys"
    export SDCLANG_AE_CONFIG="${QCPATH}/common-noship/etc/sdclang.json"
    export SDCLANG_CONFIG="${QCPATH}/common/config/sdclang.json"
    if [ -f "$(pwd)/${QCPATH}/qrsp/mpgen/mpgen.py" ]; then
        export RTIC_MPGEN="python $(pwd)/${QCPATH}/qrsp/mpgen/mpgen.py"
    fi
including vendor/qcom/proprietary/prebuilt_HY11/vendorsetup.sh
刪除之前下載時的鏈接文件,重新建立相對路徑的軟鏈接
links_dir="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))"
links_path="$(dirname $(readlink -e "${BASH_SOURCE[0]}"))/links"
failed_links=""
count=0
if [ -f "$links_path" ];then
  total_links=$(cat $links_dir/*links| wc -l)
  for i in $(cat $links_dir/*links);do
    src=$(echo $i | awk -F:: '{print $1}')
    dest=$(echo $i | awk -F:: '{print $2}')
    if [ -e "$dest" ];then
      echo rm -rf $dest
      rm -rf $dest
    fi
    if [[ -e $src && ! -e $dest ]];then
      mkdir -p $(dirname $dest)
      echo $src
      echo $dest
      ln -srf $src $dest
      count=$(($count + 1))
    else
      failed_links="$failed_links $i"
    fi
  done
  if [ ! -z "$failed_links" ];then
    echo "*****Could not create symlink*******"
    echo $failed_links | sed 's/[[:space:]]/\n/g'
    echo "****************END******************"
  fi
  echo "Created $count symlinks out of $total_links mapped links.."
fi

Created 12 symlinks out of 12 mapped links..


7、addcompletions

function addcompletions()
{
    local T dir f

    # Keep us from trying to run in something that isn't bash.
    if [ -z "${BASH_VERSION}" ]; then
        return
    fi

    # Keep us from trying to run in bash that's too old.
    if [ ${BASH_VERSINFO[0]} -lt 3 ]; then
        return
    fi

    dir="sdk/bash_completion"
    if [ -d ${dir} ]; then
        for f in `/bin/ls ${dir}/[a-z]*.bash 2> /dev/null`; do
            echo "including $f"
            . $f
        done
    fi

    complete -C "bit --tab" bit
}

including sdk/bash_completion/adb.bash
    complete -F _adb adb   定義adb命令的Tab補全函數


二、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]*$")        匹配lunch數字裏面的選項值
    then
        if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
        then
            selection=${LUNCH_MENU_CHOICES[$(($answer-1))]}
        fi
    else
        selection=$answer-1                                 直接lunch + 選項值
    fi

    export TARGET_BUILD_APPS=

    local product variant_and_version variant version

    product=${selection%%-*} # Trim everything after first dash            刪掉第一個-和其右邊的字符
    variant_and_version=${selection#*-} # Trim everything up to first dash        刪除第一個-和其左邊的字符
    if [ "$variant_and_version" != "$selection" ]; then
        variant=${variant_and_version%%-*}
        if [ "$variant" != "$variant_and_version" ]; then
            version=${variant_and_version#*-}
        fi
    fi

    if [ -z "$product" ]
    then
        echo
        echo "Invalid lunch combo: $selection"
        return 1
    fi

    TARGET_PRODUCT=$product \
    TARGET_BUILD_VARIANT=$variant \
    TARGET_PLATFORM_VERSION=$version \
    build_build_var_cache


    function build_build_var_cache()     # Get all the build variables needed by this script in a single call to the build system.獲取所需的所有構建變量
{
    local T=$(gettop)  gettop函數從指定的$TOP目錄或當前目錄開始查找build/core/envsetup.mk文件,並將能找到該文件的目錄返回給調用函數作爲操作的根目錄 
    # Grep out the variable names from the script.
    cached_vars=`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
    cached_abs_vars=`cat $T/build/envsetup.sh | tr '()' '  ' | awk '{for(i=1;i<=NF;i++) if($i~/get_abs_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
    # Call the build system to dump the "<val>=<value>" pairs as a shell script.
    build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
                        --vars="$cached_vars" \
                        --abs-vars="$cached_abs_vars" \
                        --var-prefix=var_cache_ \
                        --abs-var-prefix=abs_var_cache_`

        soong_ui.bashL:
                         
        export TRACE_BEGIN_SOONG=$(date +%s%N)
        export ORIGINAL_PWD=${PWD}
        export TOP=$(gettop)
        source ${TOP}/build/soong/scripts/microfactory.bash
            export GOROOT="${TOP}/prebuilts/go/linux-x86/"
            source ${TOP}/build/blueprint/microfactory/microfactory.bash
        soong_build_go soong_ui android/soong/cmd/soong_build_go    實際上執行 ${TOP}/prebuilts/go/linux-x86/bin/go run 加參數      生成soong_ui命令
        cd ${TOP}
        exec "$(getoutdir)/soong_ui" "$@"            soong_ui入口,執行soong流程    其實從執行結果輸出來說,就是把上面的cached_vars和cached_abs_vars所有的變量值全部賦好


        :

    local ret=$?
    if [ $ret -ne 0 ]
    then
        unset build_dicts_script
        return $ret
    fi
    # Execute the script to store the "<val>=<value>" pairs as shell variables.
    eval "$build_dicts_script"                    再次執行上面的生成的變量,在shell上面執行,讓這些值被編譯系統知道
    ret=$?
    unset build_dicts_script
    if [ $ret -ne 0 ]
    then
        return $ret
    fi
    BUILD_VAR_CACHE_READY="true"
}


    if [ $? -ne 0 ]
    then
        return 1
    fi

    export TARGET_PRODUCT=$(get_build_var TARGET_PRODUCT)
    export TARGET_BUILD_VARIANT=$(get_build_var TARGET_BUILD_VARIANT)
    if [ -n "$version" ]; then
      export TARGET_PLATFORM_VERSION=$(get_build_var TARGET_PLATFORM_VERSION)
    else
      unset TARGET_PLATFORM_VERSION
    fi
    export TARGET_BUILD_TYPE=release

    echo

    set_stuff_for_environment        export一些變量值
    printconfig
    destroy_build_var_cache         unset cached_vars和cached_abs_vars這些變量
}


三、make
頂層Makefile
include build/make/core/main.mk

include $(BUILD_SYSTEM)/Makefile     include build/make/core/Makefile

Makefile 中的第一個目標爲默認目標,我們可以通過 .DEFAULT_GOAL 這個特殊的僞目標來覆蓋掉默認的行爲。

.PHONY: droid
DEFAULT_GOAL := droid
$(DEFAULT_GOAL): droid_targets

.PHONY: droid_targets
droid_targets:

ifneq ($(TARGET_BUILD_APPS),)
  # If this build is just for apps, only build apps and not the full system by default.
droid_targets: apps_only
else 
droid_targets: droidcore dist_files

.PHONY: droidcore
droidcore: files \
    systemimage \
    $(INSTALLED_BOOTIMAGE_TARGET) \
    $(INSTALLED_RECOVERYIMAGE_TARGET) \
    $(INSTALLED_VBMETAIMAGE_TARGET) \
    $(INSTALLED_USERDATAIMAGE_TARGET) \
    $(INSTALLED_CACHEIMAGE_TARGET) \
    $(INSTALLED_BPTIMAGE_TARGET) \
    $(INSTALLED_VENDORIMAGE_TARGET) \
    $(INSTALLED_PRODUCTIMAGE_TARGET) \
    $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
    $(INSTALLED_FILES_FILE) \
    $(INSTALLED_FILES_FILE_VENDOR) \
    $(INSTALLED_FILES_FILE_PRODUCT) \
    $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
    soong_docs


# Include all of the makefiles in the system
#

subdir_makefiles := $(SOONG_ANDROID_MK) $(file <$(OUT_DIR)/.module_paths/Android.mk.list)

modules_to_install := $(sort \
    $(ALL_DEFAULT_INSTALLED_MODULES) \                               
    $(product_FILES) \
    $(foreach tag,$(tags_to_install),$($(tag)_MODULES)) \      與當前編譯類型對應的模塊文件 (debug/userdebug 之類的)
    $(CUSTOM_MODULES) \
  )

board_config_mk := \
    $(strip $(sort $(wildcard \
        $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
        $(shell test -d device && find -L device -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
        $(shell test -d vendor && find -L vendor -maxdepth 4 -path '*/$(TARGET_DEVICE)/BoardConfig.mk') \
    )))

# Read in all of the product definitions specified by the AndroidProducts.mk
# files in the tree.
all_product_configs := $(get-all-product-makefiles)                 產品Makefie文件列表

define get-all-product-makefiles
$(call get-product-makefiles,$(_find-android-products-files))
endef

current_product_makefile  當前指定的產品所加載的Makefile文件列表

$(call import-products, $(current_product_makefile))    Import just the current product makefile

經過import-products後 全部變量都變成PRODUCTS.build/target/product/xxx.mk.PRODUCT_PACKAGE這種

所以要用下面這種格式過濾product_MODULES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)  要安裝的模塊名稱列表

product_FILES := $(call module-installed-files, $(product_MODULES))   module-installed-files來獲得要安裝的模塊所對應的文件,也就是要安裝的模塊經過編譯之後生成的文件,這些文件就保存在變量product_FILES中

INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))     調用函數resolve-short-product-name解析環境變量TARGET_PRODUCT的值,將它變成一個Makefile文件路徑。並且保存在變量INTERNAL_PRODUCT中

TARGET_PRODUCT:   lunch帶進來的

TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)  找到一個名稱爲PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE的變量,並且將它的值保存另外一個變量TARGET_DEVICE中 用來描述當前指定的產品的名稱。

      ALL_DEFAULT_INSTALLED_MODULES := $(modules_to_install)           
    include $(BUILD_SYSTEM)/Makefile                                  追加ALL_DEFAULT_INSTALLED_MODULES變量
    modules_to_install := $(sort $(ALL_DEFAULT_INSTALLED_MODULES))    追加後再賦值回modules_to_install


files: $(modules_to_install) \
       $(INSTALLED_ANDROID_INFO_TXT_TARGET)


systemimage: $(INSTALLED_SYSTEMIMAGE)

$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)
    @echo "Install system fs image: $@"
    $(copy-file-to-target)
    $(hide) $(call assert-max-image-size,$@ $(RECOVERY_FROM_BOOT_PATCH),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))


$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(BUILD_IMAGE_SRCS)
    $(call build-systemimage-target,$@)


FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)


INTERNAL_SYSTEMIMAGE_FILES := $(filter $(TARGET_OUT)/%, \
    $(ALL_GENERATED_SOURCES) \
    $(ALL_DEFAULT_INSTALLED_MODULES) \
    $(PDK_FUSION_SYSIMG_FILES) \
    $(RECOVERY_RESOURCE_ZIP)) \
    $(PDK_FUSION_SYMLINK_STAMP)

要編譯的文件主要是由   filter $(TARGET_OUT)/% 從$(ALL_DEFAULT_INSTALLED_MODULES) \裏面過濾出來

例如userdata的
INTERNAL_USERDATAIMAGE_FILES := \
    $(filter $(TARGET_OUT_DATA)/%,$(ALL_DEFAULT_INSTALLED_MODULES))

    ALL_DEFAULT_INSTALLED_MODULES已經包含了對應產品的所有模塊


build-systemimage-target
        build/make/tools/releasetools/build_image.py              主要根據system文件目錄,輸出名字等參數生成system.img


$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(AVBTOOL) $(INTERNAL_BOOTIMAGE_FILES) $(BOARD_AVB_BOOT_KEY_PATH)
    $(call pretty,"Target boot image: $@")
    $(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(INTERNAL_MKBOOTIMG_VERSION_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@
    $(hide) $(call assert-max-image-size,$@,$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE)))
    $(hide) $(AVBTOOL) add_hash_footer \
      --image $@ \
      --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
      --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
      $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS)


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章