diff --git a/android/config.go b/android/config.go index 3ea361e8a..789911935 100644 --- a/android/config.go +++ b/android/config.go @@ -714,6 +714,10 @@ func (c *config) UseGoma() bool { return Bool(c.productVariables.UseGoma) } +func (c *config) UseRBE() bool { + return Bool(c.productVariables.UseRBE) +} + func (c *config) RunErrorProne() bool { return c.IsEnvTrue("RUN_ERROR_PRONE") } diff --git a/android/variable.go b/android/variable.go index e643c0ebd..28a8d0c0f 100644 --- a/android/variable.go +++ b/android/variable.go @@ -192,6 +192,7 @@ type productVariables struct { HostStaticBinaries *bool `json:",omitempty"` Binder32bit *bool `json:",omitempty"` UseGoma *bool `json:",omitempty"` + UseRBE *bool `json:",omitempty"` Debuggable *bool `json:",omitempty"` Eng *bool `json:",omitempty"` Treble_linker_namespaces *bool `json:",omitempty"` diff --git a/ui/build/Android.bp b/ui/build/Android.bp index 1ddaf68a6..6f81c1730 100644 --- a/ui/build/Android.bp +++ b/ui/build/Android.bp @@ -52,6 +52,7 @@ bootstrap_go_package { "ninja.go", "path.go", "proc_sync.go", + "rbe.go", "signal.go", "soong.go", "test_build.go", diff --git a/ui/build/build.go b/ui/build/build.go index 0ae06d61e..58b6da94e 100644 --- a/ui/build/build.go +++ b/ui/build/build.go @@ -161,6 +161,11 @@ func Build(ctx Context, config Config, what int) { startGoma(ctx, config) } + if config.StartRBE() { + // Ensure RBE proxy is started + startRBE(ctx, config) + } + if what&BuildProductConfig != 0 { // Run make for product config runMakeProductConfig(ctx, config) diff --git a/ui/build/config.go b/ui/build/config.go index 7eb3a7252..b105dc0de 100644 --- a/ui/build/config.go +++ b/ui/build/config.go @@ -493,6 +493,30 @@ func (c *configImpl) StartGoma() bool { return true } +func (c *configImpl) UseRBE() bool { + if v, ok := c.environ.Get("USE_RBE"); ok { + v = strings.TrimSpace(v) + if v != "" && v != "false" { + return true + } + } + return false +} + +func (c *configImpl) StartRBE() bool { + if !c.UseRBE() { + return false + } + + if v, ok := c.environ.Get("NOSTART_RBE"); ok { + v = strings.TrimSpace(v) + if v != "" && v != "false" { + return false + } + } + return true +} + // RemoteParallel controls how many remote jobs (i.e., commands which contain // gomacc) are run in parallel. Note the parallelism of all other jobs is // still limited by Parallel() diff --git a/ui/build/ninja.go b/ui/build/ninja.go index 7994f3a2d..7497c94bd 100644 --- a/ui/build/ninja.go +++ b/ui/build/ninja.go @@ -43,7 +43,7 @@ func runNinja(ctx Context, config Config) { args = append(args, config.NinjaArgs()...) var parallel int - if config.UseGoma() { + if config.UseGoma() || config.UseRBE() { parallel = config.RemoteParallel() } else { parallel = config.Parallel() diff --git a/ui/build/rbe.go b/ui/build/rbe.go new file mode 100644 index 000000000..c80b8ea7d --- /dev/null +++ b/ui/build/rbe.go @@ -0,0 +1,52 @@ +// Copyright 2019 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package build + +import ( + "path/filepath" + + "android/soong/ui/metrics" +) + +const bootstrapCmd = "bootstrap" +const rbeLeastNProcs = 2500 +const rbeLeastNFiles = 16000 + +func startRBE(ctx Context, config Config) { + ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap") + defer ctx.EndTrace() + + if u := ulimitOrFatal(ctx, config, "-u"); u < rbeLeastNProcs { + ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, rbeLeastNProcs) + } + if n := ulimitOrFatal(ctx, config, "-n"); n < rbeLeastNFiles { + ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, rbeLeastNFiles) + } + + var rbeBootstrap string + if rbeDir, ok := config.Environment().Get("RBE_DIR"); ok { + rbeBootstrap = filepath.Join(rbeDir, bootstrapCmd) + } else if home, ok := config.Environment().Get("HOME"); ok { + rbeBootstrap = filepath.Join(home, "rbe", bootstrapCmd) + } else { + ctx.Fatalln("rbe bootstrap not found") + } + + cmd := Command(ctx, config, "bootstrap", rbeBootstrap) + + if output, err := cmd.CombinedOutput(); err != nil { + ctx.Fatalf("rbe bootstrap failed with: %v\n%s\n", err, output) + } +}