diff --git a/android/config.go b/android/config.go index eff9fdd5b..cadc929c9 100644 --- a/android/config.go +++ b/android/config.go @@ -1195,6 +1195,10 @@ func (c *config) UseGoma() bool { return Bool(c.productVariables.UseGoma) } +func (c *config) UseABFS() bool { + return Bool(c.productVariables.UseABFS) +} + func (c *config) UseRBE() bool { return Bool(c.productVariables.UseRBE) } diff --git a/android/variable.go b/android/variable.go index eb0e210c5..df0e59ce1 100644 --- a/android/variable.go +++ b/android/variable.go @@ -294,6 +294,7 @@ type ProductVariables struct { HostStaticBinaries *bool `json:",omitempty"` Binder32bit *bool `json:",omitempty"` UseGoma *bool `json:",omitempty"` + UseABFS *bool `json:",omitempty"` UseRBE *bool `json:",omitempty"` UseRBEJAVAC *bool `json:",omitempty"` UseRBER8 *bool `json:",omitempty"` diff --git a/ui/build/build.go b/ui/build/build.go index c7319ed33..49ac791ce 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -211,9 +211,38 @@ func checkRAM(ctx Context, config Config) { } } +func abfsBuildStarted(ctx Context, config Config) { + abfsBox := config.PrebuiltBuildTool("abfsbox") + cmdArgs := []string{"build-started", "--"} + cmdArgs = append(cmdArgs, config.Arguments()...) + cmd := Command(ctx, config, "abfsbox", abfsBox, cmdArgs...) + cmd.Sandbox = noSandbox + cmd.RunAndPrintOrFatal() +} + +func abfsBuildFinished(ctx Context, config Config, finished bool) { + var errMsg string + if !finished { + errMsg = "build was interrupted" + } + abfsBox := config.PrebuiltBuildTool("abfsbox") + cmdArgs := []string{"build-finished", "-e", errMsg, "--"} + cmdArgs = append(cmdArgs, config.Arguments()...) + cmd := Command(ctx, config, "abfsbox", abfsBox, cmdArgs...) + cmd.RunAndPrintOrFatal() +} + // Build the tree. Various flags in `config` govern which components of // the build to run. func Build(ctx Context, config Config) { + done := false + if config.UseABFS() { + abfsBuildStarted(ctx, config) + defer func() { + abfsBuildFinished(ctx, config, done) + }() + } + ctx.Verboseln("Starting build with args:", config.Arguments()) ctx.Verboseln("Environment:", config.Environment().Environ()) @@ -351,6 +380,7 @@ func Build(ctx Context, config Config) { if what&RunDistActions != 0 { runDistActions(ctx, config) } + done = true } func updateBuildIdDir(ctx Context, config Config) { diff --git a/ui/build/config.go b/ui/build/config.go index 2470f843d..631b76f03 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -1270,9 +1270,25 @@ func (c *configImpl) canSupportRBE() bool { if !c.StubbyExists() && strings.Contains(authType, "use_google_prod_creds") { return false } + if c.UseABFS() { + return false + } return true } +func (c *configImpl) UseABFS() bool { + if v, ok := c.environ.Get("NO_ABFS"); ok { + v = strings.ToLower(strings.TrimSpace(v)) + if v == "true" || v == "1" { + return false + } + } + + abfsBox := c.PrebuiltBuildTool("abfsbox") + err := exec.Command(abfsBox, "hash", srcDirFileCheck).Run() + return err == nil +} + func (c *configImpl) UseRBE() bool { // These alternate modes of running Soong do not use RBE / reclient. if c.Queryview() || c.JsonModuleGraph() { @@ -1585,6 +1601,23 @@ func (c *configImpl) HostPrebuiltTag() string { } } +func (c *configImpl) KatiBin() string { + binName := "ckati" + if c.UseABFS() { + binName = "ckati-wrap" + } + + return c.PrebuiltBuildTool(binName) +} + +func (c *configImpl) NinjaBin() string { + binName := "ninja" + if c.UseABFS() { + binName = "ninjago" + } + return c.PrebuiltBuildTool(binName) +} + func (c *configImpl) PrebuiltBuildTool(name string) string { if v, ok := c.environ.Get("SANITIZE_HOST"); ok { if sanitize := strings.Fields(v); inList("address", sanitize) { diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go index e77df44a5..5df3a959b 100644 --- a/ui/build/dumpvars.go +++ b/ui/build/dumpvars.go @@ -93,7 +93,7 @@ func dumpMakeVars(ctx Context, config Config, goals, vars []string, write_soong_ defer tool.Finish() cmd := Command(ctx, config, "dumpvars", - config.PrebuiltBuildTool("ckati"), + config.KatiBin(), "-f", "build/make/core/config.mk", "--color_warnings", "--kati_stats", diff --git a/ui/build/kati.go b/ui/build/kati.go index d599c99a7..a0efd2c88 100644 --- a/ui/build/kati.go +++ b/ui/build/kati.go @@ -84,7 +84,7 @@ func writeValueIfChanged(ctx Context, config Config, dir string, filename string // arguments, and a custom function closure to mutate the environment Kati runs // in. func runKati(ctx Context, config Config, extraSuffix string, args []string, envFunc func(*Environment)) { - executable := config.PrebuiltBuildTool("ckati") + executable := config.KatiBin() // cKati arguments. args = append([]string{ // Instead of executing commands directly, generate a Ninja file. diff --git a/ui/build/ninja.go b/ui/build/ninja.go index 1935e7210..b5e74b422 100644 --- a/ui/build/ninja.go +++ b/ui/build/ninja.go @@ -49,7 +49,7 @@ func runNinjaForBuild(ctx Context, config Config) { nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo) defer nr.Close() - executable := config.PrebuiltBuildTool("ninja") + executable := config.NinjaBin() args := []string{ "-d", "keepdepfile", "-d", "keeprsp", diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go index edb3b66d4..5c3fec15e 100644 --- a/ui/build/sandbox_linux.go +++ b/ui/build/sandbox_linux.go @@ -200,6 +200,9 @@ func (c *Cmd) wrapSandbox() { // Only log important warnings / errors "-q", } + if c.config.UseABFS() { + sandboxArgs = append(sandboxArgs, "-B", "{ABFS_DIR}") + } // Mount srcDir RW allowlists as Read-Write if len(c.config.sandboxConfig.SrcDirRWAllowlist()) > 0 && !c.config.sandboxConfig.SrcDirIsRO() { diff --git a/ui/build/soong.go b/ui/build/soong.go index e18cc2579..2ccdfecd8 100644 --- a/ui/build/soong.go +++ b/ui/build/soong.go @@ -661,7 +661,7 @@ func runSoong(ctx Context, config Config) { } ninjaArgs = append(ninjaArgs, targets...) - ninjaCmd := config.PrebuiltBuildTool("ninja") + ninjaCmd := config.NinjaBin() if config.useN2 { ninjaCmd = config.PrebuiltBuildTool("n2") }