一、android build system编译系统概述
二、envsetup.sh脚本(Android10)
三、soong_ui.bash脚本
四、soong_ui的main.go
五、kati中调用main.mk
六、make目录中的main.mk
七、AndroidProducts.mk
八、module-info.json
九、子模块的执行
kati调用关系
从/build/soong/ui/build/build.go
文件中
// Build the tree. The 'what' argument can be used to chose which components of
// the build to run.
func Build(ctx Context, config Config, what int) {
...
if what&BuildKati != 0 {
// Run ckati
genKatiSuffix(ctx, config)
runKatiCleanSpec(ctx, config)
runKatiBuild(ctx, config)
runKatiPackage(ctx, config)
ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
} else {
...
}
...
}
从这里我们就可以看到kati依次被调用了那些函数:
// Run ckati
genKatiSuffix(ctx, config)
runKatiCleanSpec(ctx, config)
runKatiBuild(ctx, config)
runKatiPackage(ctx, config)
ioutil.WriteFile(config.LastKatiSuffixFile(), []byte(config.KatiSuffix()), 0777)
runKatiBuild函数
设置参数,然后调用runKati
函数
这里可以看到,参数中指定了makefile的入口是build/make/core/main.mk
func runKatiBuild(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunKati, "kati build")
defer ctx.EndTrace()
args := []string{
"--writable", config.OutDir() + "/",
"-f", "build/make/core/main.mk",
}
// PDK builds still uses a few implicit rules
if !config.IsPdkBuild() {
args = append(args, "--werror_implicit_rules")
}
if !config.BuildBrokenDupRules() {
args = append(args, "--werror_overriding_commands")
}
if !config.BuildBrokenPhonyTargets() {
args = append(args,
"--werror_real_to_phony",
"--werror_phony_looks_real",
"--werror_writable")
}
args = append(args, config.KatiArgs()...)
args = append(args,
"SOONG_MAKEVARS_MK="+config.SoongMakeVarsMk(),
"SOONG_ANDROID_MK="+config.SoongAndroidMk(),
"TARGET_DEVICE_DIR="+config.TargetDeviceDir(),
"KATI_PACKAGE_MK_DIR="+config.KatiPackageMkDir())
runKati(ctx, config, katiBuildSuffix, args, func(env *Environment) {})
}
runKati函数
func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) {
executable := config.PrebuiltBuildTool("ckati")
args = append([]string{
"--ninja",
"--ninja_dir=" + config.OutDir(),
"--ninja_suffix=" + config.KatiSuffix() + extraSuffix,
"--no_ninja_prelude",
"--regen",
"--ignore_optional_include=" + filepath.Join(config.OutDir(), "%.P"),
"--detect_android_echo",
"--color_warnings",
"--gen_all_targets",
"--use_find_emulator",
"--werror_find_emulator",
"--no_builtin_rules",
"--werror_suffix_rules",
"--warn_real_to_phony",
"--warn_phony_looks_real",
"--top_level_phony",
"--kati_stats",
}, args...)
if config.Environment().IsEnvTrue("EMPTY_NINJA_FILE") {
args = append(args, "--empty_ninja_file")
}
cmd := Command(ctx, config, "ckati", executable, args...)
cmd.Sandbox = katiSandbox
pipe, err := cmd.StdoutPipe()
if err != nil {
ctx.Fatalln("Error getting output pipe for ckati:", err)
}
cmd.Stderr = cmd.Stdout
envFunc(cmd.Environment)
if _, ok := cmd.Environment.Get("BUILD_USERNAME"); !ok {
u, err := user.Current()
if err != nil {
ctx.Println("Failed to get current user")
}
cmd.Environment.Set("BUILD_USERNAME", u.Username)
}
if _, ok := cmd.Environment.Get("BUILD_HOSTNAME"); !ok {
hostname, err := os.Hostname()
if err != nil {
ctx.Println("Failed to read hostname")
}
cmd.Environment.Set("BUILD_HOSTNAME", hostname)
}
cmd.StartOrFatal()
status.KatiReader(ctx.Status.StartTool(), pipe)
cmd.WaitOrFatal()
}