Android编译高通kernel的时候为什么有2个-j 参数
提出问题 为什么有2个 -j 参数
这里的 make -j16 -j32 怎么来的呢? 为什么有2个 -j 参数????
这个来自 ckati –ninja 这个命令,带上了这个 –ninja参数,就会设置一个 MAKE 环境变量,然后带上 -j16 这个参数了。
make的调用来自 device/qcom/common/dlkm/AndroidKernelModule.mk, 这个是 在 vendor/qcom/opensource/wlan/qcacld-3.0/Android.mk 里面引入的。
1 | 177 $(KBUILD_TARGET): $(TARGET_PREBUILT_INT_KERNEL) $(GKI_TARGET_PREBUILT_KERNEL) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(KBUILD_TARGET_GKI) |
通过上面的 makefile 内容可以看到 make 命令 来自 MAKE 这个变量,那就需要全局搜索这个变量在哪里定义了?
1 | grep -E "MAKE\s+.=" -rn device/ build |
device/zzzz/sa8295_xxxx/AndroidBoard.mk --> device/qcom/msmnile_gvmq/AndroidBoard.mk
最终查看 device/qcom/msmnile_gvmq/AndroidBoard.mk:140: MAKE := $(shell pwd)/prebuilts/build-tools/linux-x86/bin/$(MAKE)
这里
在这里也没看到 $(MAKE) 来自哪里,还需要继续查找
在 build/soong/ui/build/dumpvars.go
中 打印显示 MAKE变量如下内容:
1 | MAKE=prebuilts/build-tools/linux-x86/bin/ckati --color_warnings --kati_stats MAKECMDGOALS= |
命令行上如果make后面跟上参数就会如下内容:
1 | MAKE=prebuilts/build-tools/linux-x86/bin/ckati --color_warnings --kati_stats MAKECMDGOALS=dump-many-vars |
function make()
函数 在文件 build/envsetup.sh 中定义
build/soong/soong_ui.bash --make-mode $@
然后调用 到了 soong_ui.bash,
soong_build_go soong_ui android/soong/cmd/soong_ui
这个用来编译出来 soong_ui 命令,
这个命令编译出来放到 out/soong_ui 这里。 源码入口 build/soong/cmd/soong_ui/main.go
exec "$(getoutdir)/soong_ui" "$@"
最后调用 soong_ui 命令了 例如 exec ./out/soong_ui --make-mode -j4
1️⃣先这样, 其实这里 带的有 –ninja 参数了,在这之前会有个 ckati dump-many-vars 的执行。
1 | soong_ui --make-mode -j4 # source, lunch 之后,直接执行这个好像也可以编译 |
2️⃣后变成 ninja 进程, 这个命令来自 prebuilts/build-tools/linux-x86/bin/ninja。
1 | soong_ui --make-mode -j4 |
分析 soong_ui 执行过程
源码入口 build/soong/cmd/soong_ui/main.go,soong_ui --make-mode -j4
的情况
1.main函数入口
1.main函数入口,初始化 buildCtx build.Context结构体。config 调用了 command 结构体中的config函数。args 命令行参数。logsDir 就是 out 目录。
调用 c.run(。。。)
2.最后调用 c.run(buildCtx, config, args, logsDir)
这里的 c 就是一个 command 结构体的实例。
调用 func make
3.这个函数对应的就是func make(ctx build.Context, config build.Config, _ []string, logsDir string)
这个函数。
调用不同的函数
4.main函数中 根据RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
会调用不同的函数执行。
调用 runMakeProductConfig
4.1 调用 runMakeProductConfig(ctx, config)
根据 RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
会调用不同的函数执行。
分析 runMakeProductConfig 中是怎么影响 MAKE 这个变量的初始化的。
调用的是 ckati -f build/make/core/config.mk dump-many-vars 这样的命令。
调用 runMakeProductConfig(ctx, config) 设置一些环境变量,打印横幅 Banner,就是那个 等号 2行之间的 环境变量的打印显示。ui/build/dumpvars.go文件中。
在 runMakeProductConfig(ctx, config) 执行下面这个命令,然后就会stdout打印出来一些环境变量的值。
比较关键的是一个 DUMP_MANY_VARS=”NINJA_GOALS MAKE” 变量,这个决定会打印哪些变量。
下面是一个模拟调用的例子:
1 | DUMP_MANY_VARS="NINJA_GOALS MAKE" BUILD_DATETIME_FILE=out/build_date.txt TMPDIR=out/.temp OUT_DIR=out \ |
1 | DUMP_MANY_VARS="MAKE" BUILD_DATETIME_FILE=out/build_date.txt TMPDIR=out/.temp OUT_DIR=out \ |
这么执行 其实是调用了 build/make/core/dumpvar.mk 中的 dump-many-vars 目标。
打印出来 MAKE 这个变量的值是这个
1 | MAKE='./prebuilts/build-tools/linux-x86/bin/ckati --color_warnings --kati_stats MAKECMDGOALS=' |
去chati中的源码寻找答案
在 ckati 源码中 src/main.cc 文件中 找到如下代码
1 | if (g_flags.generate_ninja) { // 如果命令行 带上 "--ninja" 选项 这里就会是 true,进入if 判断中了 |
调用 runSoong(ctx, config)
4.2 调用 runSoong(ctx, config)
根据 RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
会调用不同的函数执行。
1 |
|
这一步说是 要 生成 build.ninja
调用 runKatiCleanSpec(ctx, config)
4.3 调用 runKatiCleanSpec(ctx, config)
根据RunAll = RunProductConfig | RunSoong | RunKati | RunKatiNinja | RunNinja
会调用不同的函数执行。
1 | prebuilts/build-tools/linux-x86/bin/ckati --ninja --ninja_dir=out --ninja_suffix=-sa8295_xxxx-cleanspec |
1 | runKatiCleanSpec(ctx, config) -> runKati() --> cmd := Command(ctx, config, "ckati", executable, args...) |
调用 runKatiBuild
4.4 调用 runKatiBuild(ctx Context, config Config)
1 | prebuilts/build-tools/linux-x86/bin/ckati --ninja --ninja_dir=out --ninja_suffix=-sa8295_xxxx --no_ninja_prelude --use_ninja_phony_output --use_ninja_symlink_outputs --regen --ignore_optional_include=out/%.P --detect_android_echo --color_warnings --gen_all_targets --use_find_emulator --werror_find_emulator --no_builtin_rules --werror_suffix_rules --werror_real_to_phony --top_level_phony --werror_phony_looks_real --werror_writable --kati_stats --writable out/ --werror_implicit_rules -f build/make/core/main.mk SOONG_MAKEVARS_MK=out/soong/make_vars-sa8295_xxxx.mk SOONG_ANDROID_MK=out/soong/Android-sa8295_xxxx.mk TARGET_DEVICE_DIR=device/zzzz/sa8295_xxxx KATI_PACKAGE_MK_DIR=out/target/product/sa8295_xxxx/obj/CONFIG/kati_packaging |
1 | runKatiBuild(ctx Context, config Config) -> runKati() --> cmd := Command(ctx, config, "ckati", executable, args...) |
调用 runKatiPackage
4.5 调用 runKatiPackage(ctx Context, config Config)
1 | prebuilts/build-tools/linux-x86/bin/ckati --ninja --ninja_dir=out --ninja_suffix=-sa8295_xxxx-package --no_ninja_prelude --use_ninja_phony_output --use_ninja_symlink_outputs --regen --ignore_optional_include=out/%.P --detect_android_echo --color_warnings --gen_all_targets --use_find_emulator --werror_find_emulator --no_builtin_rules --werror_suffix_rules --werror_real_to_phony --top_level_phony --werror_phony_looks_real --werror_writable --kati_stats --writable out/dist/ --werror_implicit_rules --werror_overriding_commands -f build/make/packaging/main.mk KATI_PACKAGE_MK_DIR=out/target/product/sa8295_xxxx/obj/CONFIG/kati_packaging |
1 | runKatiPackage(ctx Context, config Config) -> runKati() --> cmd := Command(ctx, config, "ckati", executable, args...) |
调用 runNinjaForBuild
- main函数的最后 会有个 runNinjaForBuild(ctx, config) 的调用,这里就又 调用到 ninja 这个命令上了。
1 | prebuilts/build-tools/linux-x86/bin/ninja -d keepdepfile -d keeprsp -d stats \ |