xref: /aosp_15_r20/build/soong/ui/build/rbe.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2019 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage build
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"os"
20*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
21*333d2b36SAndroid Build Coastguard Worker	"runtime"
22*333d2b36SAndroid Build Coastguard Worker	"strings"
23*333d2b36SAndroid Build Coastguard Worker
24*333d2b36SAndroid Build Coastguard Worker	"android/soong/remoteexec"
25*333d2b36SAndroid Build Coastguard Worker	"android/soong/ui/metrics"
26*333d2b36SAndroid Build Coastguard Worker)
27*333d2b36SAndroid Build Coastguard Worker
28*333d2b36SAndroid Build Coastguard Workerconst (
29*333d2b36SAndroid Build Coastguard Worker	rbeLeastNProcs = 2500
30*333d2b36SAndroid Build Coastguard Worker	rbeLeastNFiles = 16000
31*333d2b36SAndroid Build Coastguard Worker
32*333d2b36SAndroid Build Coastguard Worker	// prebuilt RBE binaries
33*333d2b36SAndroid Build Coastguard Worker	bootstrapCmd = "bootstrap"
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Worker	// RBE metrics proto buffer file
36*333d2b36SAndroid Build Coastguard Worker	rbeMetricsPBFilename = "rbe_metrics.pb"
37*333d2b36SAndroid Build Coastguard Worker
38*333d2b36SAndroid Build Coastguard Worker	defaultOutDir = "out"
39*333d2b36SAndroid Build Coastguard Worker)
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Workerfunc rbeCommand(ctx Context, config Config, rbeCmd string) string {
42*333d2b36SAndroid Build Coastguard Worker	var cmdPath string
43*333d2b36SAndroid Build Coastguard Worker	if rbeDir := config.rbeDir(); rbeDir != "" {
44*333d2b36SAndroid Build Coastguard Worker		cmdPath = filepath.Join(rbeDir, rbeCmd)
45*333d2b36SAndroid Build Coastguard Worker	} else {
46*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("rbe command path not found")
47*333d2b36SAndroid Build Coastguard Worker	}
48*333d2b36SAndroid Build Coastguard Worker
49*333d2b36SAndroid Build Coastguard Worker	if _, err := os.Stat(cmdPath); err != nil && os.IsNotExist(err) {
50*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("rbe command %q not found", rbeCmd)
51*333d2b36SAndroid Build Coastguard Worker	}
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Worker	return cmdPath
54*333d2b36SAndroid Build Coastguard Worker}
55*333d2b36SAndroid Build Coastguard Worker
56*333d2b36SAndroid Build Coastguard Workerfunc getRBEVars(ctx Context, config Config) map[string]string {
57*333d2b36SAndroid Build Coastguard Worker	vars := map[string]string{
58*333d2b36SAndroid Build Coastguard Worker		"RBE_log_dir":          config.rbeProxyLogsDir(),
59*333d2b36SAndroid Build Coastguard Worker		"RBE_re_proxy":         config.rbeReproxy(),
60*333d2b36SAndroid Build Coastguard Worker		"RBE_exec_root":        config.rbeExecRoot(),
61*333d2b36SAndroid Build Coastguard Worker		"RBE_output_dir":       config.rbeProxyLogsDir(),
62*333d2b36SAndroid Build Coastguard Worker		"RBE_proxy_log_dir":    config.rbeProxyLogsDir(),
63*333d2b36SAndroid Build Coastguard Worker		"RBE_cache_dir":        config.rbeCacheDir(),
64*333d2b36SAndroid Build Coastguard Worker		"RBE_download_tmp_dir": config.rbeDownloadTmpDir(),
65*333d2b36SAndroid Build Coastguard Worker		"RBE_platform":         "container-image=" + remoteexec.DefaultImage,
66*333d2b36SAndroid Build Coastguard Worker	}
67*333d2b36SAndroid Build Coastguard Worker	if config.StartRBE() {
68*333d2b36SAndroid Build Coastguard Worker		name, err := config.rbeSockAddr(absPath(ctx, config.rbeTmpDir()))
69*333d2b36SAndroid Build Coastguard Worker		if err != nil {
70*333d2b36SAndroid Build Coastguard Worker			ctx.Fatalf("Error retrieving socket address: %v", err)
71*333d2b36SAndroid Build Coastguard Worker			return nil
72*333d2b36SAndroid Build Coastguard Worker		}
73*333d2b36SAndroid Build Coastguard Worker		vars["RBE_server_address"] = fmt.Sprintf("unix://%v", name)
74*333d2b36SAndroid Build Coastguard Worker	}
75*333d2b36SAndroid Build Coastguard Worker
76*333d2b36SAndroid Build Coastguard Worker	rf := 1.0
77*333d2b36SAndroid Build Coastguard Worker	if config.Parallel() < runtime.NumCPU() {
78*333d2b36SAndroid Build Coastguard Worker		rf = float64(config.Parallel()) / float64(runtime.NumCPU())
79*333d2b36SAndroid Build Coastguard Worker	}
80*333d2b36SAndroid Build Coastguard Worker	vars["RBE_local_resource_fraction"] = fmt.Sprintf("%.2f", rf)
81*333d2b36SAndroid Build Coastguard Worker
82*333d2b36SAndroid Build Coastguard Worker	k, v := config.rbeAuth()
83*333d2b36SAndroid Build Coastguard Worker	vars[k] = v
84*333d2b36SAndroid Build Coastguard Worker	return vars
85*333d2b36SAndroid Build Coastguard Worker}
86*333d2b36SAndroid Build Coastguard Worker
87*333d2b36SAndroid Build Coastguard Workerfunc cleanupRBELogsDir(ctx Context, config Config) {
88*333d2b36SAndroid Build Coastguard Worker	if !config.shouldCleanupRBELogsDir() {
89*333d2b36SAndroid Build Coastguard Worker		return
90*333d2b36SAndroid Build Coastguard Worker	}
91*333d2b36SAndroid Build Coastguard Worker
92*333d2b36SAndroid Build Coastguard Worker	rbeTmpDir := config.rbeProxyLogsDir()
93*333d2b36SAndroid Build Coastguard Worker	if err := os.RemoveAll(rbeTmpDir); err != nil {
94*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "\033[33mUnable to remove RBE log directory: ", err, "\033[0m")
95*333d2b36SAndroid Build Coastguard Worker	}
96*333d2b36SAndroid Build Coastguard Worker}
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Workerfunc checkRBERequirements(ctx Context, config Config) {
99*333d2b36SAndroid Build Coastguard Worker	if !config.GoogleProdCredsExist() && prodCredsAuthType(config) {
100*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("Unable to start RBE reproxy\nFAILED: Missing LOAS credentials.")
101*333d2b36SAndroid Build Coastguard Worker	}
102*333d2b36SAndroid Build Coastguard Worker
103*333d2b36SAndroid Build Coastguard Worker	if u := ulimitOrFatal(ctx, config, "-u"); u < rbeLeastNProcs {
104*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, rbeLeastNProcs)
105*333d2b36SAndroid Build Coastguard Worker	}
106*333d2b36SAndroid Build Coastguard Worker	if n := ulimitOrFatal(ctx, config, "-n"); n < rbeLeastNFiles {
107*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("max open files is insufficient: %d; want >= %d.\n", n, rbeLeastNFiles)
108*333d2b36SAndroid Build Coastguard Worker	}
109*333d2b36SAndroid Build Coastguard Worker	if _, err := os.Stat(config.rbeProxyLogsDir()); os.IsNotExist(err) {
110*333d2b36SAndroid Build Coastguard Worker		if err := os.MkdirAll(config.rbeProxyLogsDir(), 0744); err != nil {
111*333d2b36SAndroid Build Coastguard Worker			ctx.Fatalf("Unable to create logs dir (%v) for RBE: %v", config.rbeProxyLogsDir, err)
112*333d2b36SAndroid Build Coastguard Worker		}
113*333d2b36SAndroid Build Coastguard Worker	}
114*333d2b36SAndroid Build Coastguard Worker}
115*333d2b36SAndroid Build Coastguard Worker
116*333d2b36SAndroid Build Coastguard Workerfunc startRBE(ctx Context, config Config) {
117*333d2b36SAndroid Build Coastguard Worker	ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
118*333d2b36SAndroid Build Coastguard Worker	defer ctx.EndTrace()
119*333d2b36SAndroid Build Coastguard Worker
120*333d2b36SAndroid Build Coastguard Worker	ctx.Status.Status("Starting rbe...")
121*333d2b36SAndroid Build Coastguard Worker
122*333d2b36SAndroid Build Coastguard Worker	cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd))
123*333d2b36SAndroid Build Coastguard Worker
124*333d2b36SAndroid Build Coastguard Worker	if output, err := cmd.CombinedOutput(); err != nil {
125*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("Unable to start RBE reproxy\nFAILED: RBE bootstrap failed with: %v\n%s\n", err, output)
126*333d2b36SAndroid Build Coastguard Worker	}
127*333d2b36SAndroid Build Coastguard Worker}
128*333d2b36SAndroid Build Coastguard Worker
129*333d2b36SAndroid Build Coastguard Workerfunc stopRBE(ctx Context, config Config) {
130*333d2b36SAndroid Build Coastguard Worker	cmd := Command(ctx, config, "stopRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd), "-shutdown")
131*333d2b36SAndroid Build Coastguard Worker	output, err := cmd.CombinedOutput()
132*333d2b36SAndroid Build Coastguard Worker	if err != nil {
133*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("rbe bootstrap with shutdown failed with: %v\n%s\n", err, output)
134*333d2b36SAndroid Build Coastguard Worker	}
135*333d2b36SAndroid Build Coastguard Worker
136*333d2b36SAndroid Build Coastguard Worker	if !config.Environment().IsEnvTrue("ANDROID_QUIET_BUILD") && len(output) > 0 {
137*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "")
138*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, fmt.Sprintf("%s", output))
139*333d2b36SAndroid Build Coastguard Worker	}
140*333d2b36SAndroid Build Coastguard Worker}
141*333d2b36SAndroid Build Coastguard Worker
142*333d2b36SAndroid Build Coastguard Workerfunc prodCredsAuthType(config Config) bool {
143*333d2b36SAndroid Build Coastguard Worker	authVar, val := config.rbeAuth()
144*333d2b36SAndroid Build Coastguard Worker	if strings.Contains(authVar, "use_google_prod_creds") && val != "" && val != "false" {
145*333d2b36SAndroid Build Coastguard Worker		return true
146*333d2b36SAndroid Build Coastguard Worker	}
147*333d2b36SAndroid Build Coastguard Worker	return false
148*333d2b36SAndroid Build Coastguard Worker}
149*333d2b36SAndroid Build Coastguard Worker
150*333d2b36SAndroid Build Coastguard Worker// Check whether proper auth exists for RBE builds run within a
151*333d2b36SAndroid Build Coastguard Worker// Google dev environment.
152*333d2b36SAndroid Build Coastguard Workerfunc CheckProdCreds(ctx Context, config Config) {
153*333d2b36SAndroid Build Coastguard Worker	if !config.IsGooglerEnvironment() {
154*333d2b36SAndroid Build Coastguard Worker		return
155*333d2b36SAndroid Build Coastguard Worker	}
156*333d2b36SAndroid Build Coastguard Worker	if !config.StubbyExists() && prodCredsAuthType(config) {
157*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "")
158*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, fmt.Sprintf("\033[33mWARNING: %q binary not found in $PATH, follow go/build-fast-without-stubby instead for authenticating with RBE.\033[0m", "stubby"))
159*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "")
160*333d2b36SAndroid Build Coastguard Worker		return
161*333d2b36SAndroid Build Coastguard Worker	}
162*333d2b36SAndroid Build Coastguard Worker}
163*333d2b36SAndroid Build Coastguard Worker
164*333d2b36SAndroid Build Coastguard Worker// DumpRBEMetrics creates a metrics protobuf file containing RBE related metrics.
165*333d2b36SAndroid Build Coastguard Worker// The protobuf file is created if RBE is enabled and the proxy service has
166*333d2b36SAndroid Build Coastguard Worker// started. The proxy service is shutdown in order to dump the RBE metrics to the
167*333d2b36SAndroid Build Coastguard Worker// protobuf file.
168*333d2b36SAndroid Build Coastguard Workerfunc DumpRBEMetrics(ctx Context, config Config, filename string) {
169*333d2b36SAndroid Build Coastguard Worker	ctx.BeginTrace(metrics.RunShutdownTool, "dump_rbe_metrics")
170*333d2b36SAndroid Build Coastguard Worker	defer ctx.EndTrace()
171*333d2b36SAndroid Build Coastguard Worker
172*333d2b36SAndroid Build Coastguard Worker	// Remove the previous metrics file in case there is a failure or RBE has been
173*333d2b36SAndroid Build Coastguard Worker	// disable for this run.
174*333d2b36SAndroid Build Coastguard Worker	os.Remove(filename)
175*333d2b36SAndroid Build Coastguard Worker
176*333d2b36SAndroid Build Coastguard Worker	// If RBE is not enabled then there are no metrics to generate.
177*333d2b36SAndroid Build Coastguard Worker	// If RBE does not require to start, the RBE proxy maybe started
178*333d2b36SAndroid Build Coastguard Worker	// manually for debugging purpose and can generate the metrics
179*333d2b36SAndroid Build Coastguard Worker	// afterwards.
180*333d2b36SAndroid Build Coastguard Worker	if !config.StartRBE() {
181*333d2b36SAndroid Build Coastguard Worker		return
182*333d2b36SAndroid Build Coastguard Worker	}
183*333d2b36SAndroid Build Coastguard Worker
184*333d2b36SAndroid Build Coastguard Worker	outputDir := config.rbeProxyLogsDir()
185*333d2b36SAndroid Build Coastguard Worker	if outputDir == "" {
186*333d2b36SAndroid Build Coastguard Worker		ctx.Fatal("RBE output dir variable not defined. Aborting metrics dumping.")
187*333d2b36SAndroid Build Coastguard Worker	}
188*333d2b36SAndroid Build Coastguard Worker	metricsFile := filepath.Join(outputDir, rbeMetricsPBFilename)
189*333d2b36SAndroid Build Coastguard Worker
190*333d2b36SAndroid Build Coastguard Worker	// Stop the proxy first in order to generate the RBE metrics protobuf file.
191*333d2b36SAndroid Build Coastguard Worker	stopRBE(ctx, config)
192*333d2b36SAndroid Build Coastguard Worker
193*333d2b36SAndroid Build Coastguard Worker	if metricsFile == filename {
194*333d2b36SAndroid Build Coastguard Worker		return
195*333d2b36SAndroid Build Coastguard Worker	}
196*333d2b36SAndroid Build Coastguard Worker	if _, err := copyFile(metricsFile, filename); err != nil {
197*333d2b36SAndroid Build Coastguard Worker		ctx.Fatalf("failed to copy %q to %q: %v\n", metricsFile, filename, err)
198*333d2b36SAndroid Build Coastguard Worker	}
199*333d2b36SAndroid Build Coastguard Worker}
200*333d2b36SAndroid Build Coastguard Worker
201*333d2b36SAndroid Build Coastguard Worker// PrintOutDirWarning prints a warning to indicate to the user that
202*333d2b36SAndroid Build Coastguard Worker// setting output directory to a path other than "out" in an RBE enabled
203*333d2b36SAndroid Build Coastguard Worker// build can cause slow builds.
204*333d2b36SAndroid Build Coastguard Workerfunc PrintOutDirWarning(ctx Context, config Config) {
205*333d2b36SAndroid Build Coastguard Worker	if config.UseRBE() && config.OutDir() != defaultOutDir {
206*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "")
207*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "\033[33mWARNING:\033[0m")
208*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, fmt.Sprintf("Setting OUT_DIR to a path other than %v may result in slow RBE builds.", defaultOutDir))
209*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "See http://go/android_rbe_out_dir for a workaround.")
210*333d2b36SAndroid Build Coastguard Worker		fmt.Fprintln(ctx.Writer, "")
211*333d2b36SAndroid Build Coastguard Worker	}
212*333d2b36SAndroid Build Coastguard Worker}
213