对Android Q系统源码编译速度的一次优化

前言

工作中发现在MTK平台编译某一模块时,Android Q的系统源码编译速度比Android P慢了许多,需要分析下原因并改善编译速度。

从Android Q编译时的输出日志中看出:每次mm编译一个app模块时,都会打印如下信息:

$(file <out/build_number.txt) was changed, regenerating...
[  0% 0/1] initializing build system ...

接着就是长达几分钟的等待,哪怕什么代码都没改,编译依然耗费一段时间。

熟悉Android编译系统的应该知道,每次显示修改mk文件或git pull操作时都会触发.ninja文件的重新生成。这个几百M大小的文件是由ckati工具生成的,我们查看out目录下的文件,build-full_xxx-packages_noahapps_xxx_Android.mk.ninja每次都刷新了时间戳。很明显在没有修改任何源码的情况下这次生成是不必要的。

分析过程

分析build_number.txt文件为什么每次编译时都会生成,即使里面的内容是没有变化的。

1、查看build/make/core/main.mk:

# Write the build number to a file so it can be read back in
# without changing the command line every time.  Avoids rebuilds
# when using ninja.
$(shell mkdir -p $(OUT_DIR) && \
    echo -n $(BUILD_NUMBER) > $(OUT_DIR)/build_number.txt)
BUILD_NUMBER_FILE := $(OUT_DIR)/build_number.txt

可以看出build_number.txt中的内容是根据BUILD_NUMBER属性生成的。

2、查看build/make/core/Makefile:

BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \

3、查看build/make/core/config.mk:

BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
BUILD_DATETIME_FROM_FILE := $$(cat $(BUILD_DATETIME_FILE))

可以看出BUILD_NUMBER来源于BUILD_NUMBER_FROM_FILE属性,而BUILD_NUMBER_FROM_FILE又是读取out/build_number.txt的文件内容。

4、其中的关系如图

扫描二维码关注公众号,回复: 14854609 查看本文章
from
from
from
build_number.txt
BUILD_NUMBER
BUILD_NUMBER_FROM_FILE

看来形成了一个闭环链关系,等等,这不自相矛盾了吗?


5、再全局搜索BUILD_NUMBER属性是否还有赋值的地方:
发现device/mediatek/build/vendorsetup.sh:

export TEMPORARY_DISABLE_PATH_RESTRICTIONS=true
if [ "$BUILD_NUMBER" = "" ] ; then
  if [ -f "vendor/mediatek/proprietary/buildinfo/label.ini" ] ; then
    export BUILD_NUMBER=$BUILD_NUMBER
  fi
fi

看来设备厂商也有一个生成BUILD_NUMBER的方法,有可能是这里,通过初始化编译环境时也能看到相关log,一开始就加载了device目录下的vendorsetup.sh

liuke@youxuepai-PC1:~/work/P713_mt6779$ source set_env.sh 
call set_env.sh
including noah device/mediatek/build/vendorsetup.sh

加载逻辑位于build/make/envsetup.sh中的source_vendorsetup()方法

function source_vendorsetup() {
    
    
    allowed=
    for f in $(find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
        if [ -n "$allowed" ]; then
            echo "More than one 'allowed_vendorsetup_sh-files' file found, not including any vendorsetup.sh files:"
            echo "  $allowed"
            echo "  $f"
            return
        fi
        allowed="$f"
    done

    allowed_files=
    [ -n "$allowed" ] && allowed_files=$(cat "$allowed")
    for dir in device vendor product; do
        for f in $(test -d $dir && \
            find -L $dir -maxdepth 4 -name 'vendorsetup.sh' 2>/dev/null | sort); do
            if [[ -z "$allowed" || "$allowed_files" =~ $f ]]; then
            	#在这里include device目录下的vendorsetup.sh
                echo "including noah $f"; . "$f"
            else
                echo "ignoring $f, not in $allowed"
            fi
        done
    done
}

6、至此,我们再回到build/make/core/main.mk文件,删除这里生成的build_number.txt的方法:
在这里插入图片描述


7、验证编译make services:由于修改了main.mk,重新触发了.ninja文件生成所以第一次会耗时,稍微改动下java文件并再次编译发现没有生成build_number.txt和.ninja文件了,速度快了很多。

============================================
19:43:31 AllowBuildBrokenUsesNetwork: true
19:43:31 BuildBrokenUsesNetwork: true
[100% 16/16] Copy: out/target/product/yxp_752_pad/system/framework/oat/arm64/services.odex

build completed successfully (01:10 (mm:ss))(2022年 09月 28日 星期三 19:44:13 CST) 

最终实现

对比Android P下build_number.txt的生成过程:
在build/make/core/version_default.mk:

ifndef BUILD_NUMBER
  # BUILD_NUMBER should be set to the source control value that
  # represents the current state of the source code.  E.g., a
  # perforce changelist number or a git hash.  Can be an arbitrary string
  # (to allow for source control that uses something other than numbers),
  # but must be a single word and a valid file name.
  #
  # If no BUILD_NUMBER is set, create a useful "I am an engineering build
  # from this date/time" value.  Make it start with a non-digit so that
  # anyone trying to parse it as an integer will probably get "0".
  BUILD_NUMBER := eng.$(shell echo $${
     
     USER:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
  HAS_BUILD_NUMBER := false
endif

同时发现device/mediatek/build/vendorsetup.sh源码中也没有属性BUILD_NUMBER的赋值定义。
所以两个平台的build_number.txt内容形式也不一样。

Android P:eng.liuke.20220926.200349
Android Q:mp1V9110

最后我们完善下Android Q中main.mk文件build_number.txt的这块内容,避免不必要的重新生成:

$(shell mkdir -p $(OUT_DIR) && \
    echo -n $(BUILD_NUMBER) > $(OUT_DIR)/build_number.tmp; \
    if ! cmp -s $(OUT_DIR)/build_number.tmp $(OUT_DIR)/build_number.txt; then \
        mv $(OUT_DIR)/build_number.tmp $(OUT_DIR)/build_number.txt; \
    else \
        rm $(OUT_DIR)/build_number.tmp; \
    fi)

提交,万事大吉!

猜你喜欢

转载自blog.csdn.net/qq_23069607/article/details/127109660