make全编译执行过程

Post on Jul 14, 2021 by Wei Lin

make全编译执行过程

Android系统主要就是根据.mk文件进行编译的。

image-20240226221449616

make -j8

在Android源码根目录全编译的命令为:

source build/envsetup.sh
lunch <product_name>-<build_variant>
make -j8

envsetup.sh

build/envsetup.sh是一个软连接,实际指向build/make/envsetup.sh

首先在envsetup.sh中执行make函数:

function make()
{
    _wrap_build $(get_make_command "$@") "$@"
}

执行get_make_command "$@"命令:
function get_make_command()
{
    # If we're in the top of an Android tree, use soong_ui.bash instead of make
    if [ -f build/soong/soong_ui.bash ]; then
        # Always use the real make if -C is passed in
        for arg in "$@"; do
            if [[ $arg == -C* ]]; then
                echo command make
                return
            fi
        done
        echo build/soong/soong_ui.bash --make-mode
    else
        echo command make
    fi
}

build/soong/soong_ui.bash

soong_ui.bash 用来配置一些资源环境,最终回退到根目录,执行out/soong_ui –make-mode进行真正的构建。

# Save the current PWD for use in soong_ui
export ORIGINAL_PWD=${PWD}
export TOP=$(gettop)
source ${TOP}/build/soong/scripts/microfactory.bash

soong_build_go soong_ui android/soong/cmd/soong_ui
soong_build_go mk2rbc android/soong/mk2rbc/cmd
soong_build_go rbcrun rbcrun/cmd

cd ${TOP}
exec "$(getoutdir)/soong_ui" "$@"

out/soong_ui

​ out/soong_ui是一个可执行的二进制文件,是通过编译build/soong/cmd/soong_ui/main.go得来的。

分析main.go就可以得知out/soong_ui的执行流程。

在main.go中主要执行build/soong/ui/build/build.go,build.go的执行任务为:

  • runMakeProductConfig:主要配置编译参数;
  • runSoong:对工具进行编译,编译出blueprint等编译工具,把*.bp 编译成 out/soong/build.ninja;
  • runKatiBuild:加载 build/make/core/main.mk,搜集所有的Android.mk文件生成ninja文件out/build-aosp_arm.ninja;
  • runKatiPackage:加载build/make/packaging/main.mk,编译生成out/build-aosp_arm-package.ninja;
  • createCombinedBuildNinjaFile:将out/soong/build.ninja、out/build-aosp_arm.ninja和out/build-aosp_arm-package.ninja,合成为out/combined-aosp_arm.ninja;
  • runNinja:运行Ninja命令,解析combined-aosp_arm.ninja,执行编译过程;

main.mk文件分析

执行runKatiBuild时,有个重要的步骤,就是加载build/make/core/main.mk,main.mk文件是Android Build系统的主控文件。从main.mk开始,将通过include命令将其所有需要的.mk文件包含进来,最终在内存中形成一个包括所有编译脚本的集合,这个相当于一个巨大Makefile文件。Makefile文件看上去很庞大,其实主要由三种内容构成: 变量定义、函数定义和目标依赖规则,此外mk文件之间的包含也很重要。