less than 1 minute read

Kati是为了提高Android编译速度而产生的实验性的GNU make克隆的工具。本身没有提供快速编译,而是将Makefile文件转换为Ninja文件,再通过Ninja进行编译提速。 目前Android 12上,Kati(即prebuilts/build-tools/linux-x86/bin/ckati)的作用就是生成build.ninja文件

1. kati简介

Kati最开始在Go中实现的,期初开发者认为Go可以获取足够的性能,但是最终却是使得Kati的Go版本变慢了。所以后来Kati用C++重写实现,即ckati,除了C++实现,还有部分的Go和sh,这应该是考虑之后的最好性能。

kati刚开始是使用Golang编写的,但是后来验证下来发现编译速度不行,于是改成C++编写,所以现在存在两个版本:kati、ckati。在Android10.0编译过程中,是通过ckati来把makefile文件转换成ninja文件的

从Android 11开始,不再释放源码,而是直接作为prebuilts预编译资源,Android 10之前源码在android/build/kati,现在是直接调用预编译prebuilts/build-tools/linux-x86/bin/ckati工具,使用ckati工具,以及传入的一系列参数,编译出out/build-aosp_arm.ninja

1.1. 整体架构

Kati由几部分组成:

  • 解析器(Parser)
  • 评估器(Evaluator):输出构建规则(build rules)和变量表(variable table)的列表
  • 依赖构建器(Dependency builder):从构建规则列表中创建依赖图(dependency graph)
  • 执行器(Executor)
  • Ninja生成器(Ninja generator)

1.2. 代码位置

Android N、O、P代码目录在:android/build/kati/

Android 11开始,提供预编译结果文件使用:

$ find prebuilts/ -name ckati
prebuilts/build-tools/linux-x86/asan/bin/ckati
prebuilts/build-tools/linux-x86/bin/ckati
prebuilts/build-tools/darwin-x86/bin/ckati

github的source code路径为:https://github.com/google/kati

可以通过下面命令获取source code:git clone https://github.com/google/kati.git


1.3. 编译

在项目编译的时候会直接使用prebuilts/build-tools这里的ckati,详细看prebuilts/build-tools/build-prebuilts.sh,下面节选部分内容:

# Use toybox and other prebuilts even outside of the build (test running, go, etc)
export PATH=${TOP}/prebuilts/build-tools/path/${OS}-x86:$PATH

if [ -n ${build_soong} ]; then
    SOONG_OUT=${OUT_DIR}/soong
    # 路径:out/soong/host/linux-x86/bin
    SOONG_HOST_OUT=${OUT_DIR}/soong/host/${OS}-x86
    [[ -z "${clean}" ]] || rm -rf ${SOONG_OUT}
    mkdir -p ${SOONG_OUT}
    rm -rf ${SOONG_OUT}/dist ${SOONG_OUT}/dist-common
    cat > ${SOONG_OUT}/soong.variables << EOF
{
    "Allow_missing_dependencies": true,
    "HostArch":"x86_64",
    "VendorVars": {
        "cpython3": {
            "force_build_host": "true"
        }
    }
}

 SOONG_BINARIES=(
        acp
        aidl
        .....
        ckati
        hidl-gen
        hidl-lint
        m4
        make
        ninja
        ....
        }

binaries="${SOONG_BINARIES[@]/#/${SOONG_HOST_OUT}/bin/}"

2. kati用法

在Android的编译过程中,ckati会自动被使用,无须开发者担心。

单独使用时,在包含Makefile的目录下,执行ckati,效果与make基本相同。执行ckati --ninja,可以根据Makefile生成build.ninja文件,并且附带env-aosp_arm.shninja-aosp_arm.sh(在out根目录)。通过env-aosp_arm.sh来配置环境,通过执行./ninja-aosp_arm.sh来启动Ninja、使用build.ninja编译。

# (1)文件env-aosp_arm.sh内容
out$ cat env-aosp_arm.sh
#!/bin/sh
# Generated by kati unknown

# (2)文件ninja-aosp_arm.sh内容
out$ cat ninja-aosp_arm.sh
#!/bin/sh
# Generated by kati unknown

. out/env-aosp_arm.sh
exec ninja -f out/build-aosp_arm.ninja "$@"

除了--ninja以外,ckati支持很多其它参数。比如,和make一样,可以通过-f指定Makefile位置,通过-j指定线程数。


3. 参考

Leave a comment