xref: /aosp_15_r20/build/soong/remoteexec/remoteexec.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 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 remoteexec
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"sort"
20*333d2b36SAndroid Build Coastguard Worker	"strings"
21*333d2b36SAndroid Build Coastguard Worker)
22*333d2b36SAndroid Build Coastguard Worker
23*333d2b36SAndroid Build Coastguard Workerconst (
24*333d2b36SAndroid Build Coastguard Worker	// ContainerImageKey is the key identifying the container image in the platform spec.
25*333d2b36SAndroid Build Coastguard Worker	ContainerImageKey = "container-image"
26*333d2b36SAndroid Build Coastguard Worker
27*333d2b36SAndroid Build Coastguard Worker	// PoolKey is the key identifying the pool to use for remote execution.
28*333d2b36SAndroid Build Coastguard Worker	PoolKey = "Pool"
29*333d2b36SAndroid Build Coastguard Worker
30*333d2b36SAndroid Build Coastguard Worker	// DefaultImage is the default container image used for Android remote execution. The
31*333d2b36SAndroid Build Coastguard Worker	// image was built with the Dockerfile at
32*333d2b36SAndroid Build Coastguard Worker	// https://android.googlesource.com/platform/prebuilts/remoteexecution-client/+/refs/heads/master/docker/Dockerfile
33*333d2b36SAndroid Build Coastguard Worker	DefaultImage = "docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:1eb7f64b9e17102b970bd7a1af7daaebdb01c3fb777715899ef462d6c6d01a45"
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Worker	// DefaultWrapperPath is the default path to the remote execution wrapper.
36*333d2b36SAndroid Build Coastguard Worker	DefaultWrapperPath = "prebuilts/remoteexecution-client/live/rewrapper"
37*333d2b36SAndroid Build Coastguard Worker
38*333d2b36SAndroid Build Coastguard Worker	// DefaultPool is the name of the pool to use for remote execution when none is specified.
39*333d2b36SAndroid Build Coastguard Worker	DefaultPool = "default"
40*333d2b36SAndroid Build Coastguard Worker
41*333d2b36SAndroid Build Coastguard Worker	// LocalExecStrategy is the exec strategy to indicate that the action should be run locally.
42*333d2b36SAndroid Build Coastguard Worker	LocalExecStrategy = "local"
43*333d2b36SAndroid Build Coastguard Worker
44*333d2b36SAndroid Build Coastguard Worker	// RemoteExecStrategy is the exec strategy to indicate that the action should be run
45*333d2b36SAndroid Build Coastguard Worker	// remotely.
46*333d2b36SAndroid Build Coastguard Worker	RemoteExecStrategy = "remote"
47*333d2b36SAndroid Build Coastguard Worker
48*333d2b36SAndroid Build Coastguard Worker	// RemoteLocalFallbackExecStrategy is the exec strategy to indicate that the action should
49*333d2b36SAndroid Build Coastguard Worker	// be run remotely and fallback to local execution if remote fails.
50*333d2b36SAndroid Build Coastguard Worker	RemoteLocalFallbackExecStrategy = "remote_local_fallback"
51*333d2b36SAndroid Build Coastguard Worker)
52*333d2b36SAndroid Build Coastguard Worker
53*333d2b36SAndroid Build Coastguard Workervar (
54*333d2b36SAndroid Build Coastguard Worker	defaultLabels               = map[string]string{"type": "tool"}
55*333d2b36SAndroid Build Coastguard Worker	defaultExecStrategy         = LocalExecStrategy
56*333d2b36SAndroid Build Coastguard Worker	defaultEnvironmentVariables = []string{
57*333d2b36SAndroid Build Coastguard Worker		// This is a subset of the allowlist in ui/build/ninja.go that makes sense remotely.
58*333d2b36SAndroid Build Coastguard Worker		"LANG",
59*333d2b36SAndroid Build Coastguard Worker		"LC_MESSAGES",
60*333d2b36SAndroid Build Coastguard Worker		"PYTHONDONTWRITEBYTECODE",
61*333d2b36SAndroid Build Coastguard Worker	}
62*333d2b36SAndroid Build Coastguard Worker)
63*333d2b36SAndroid Build Coastguard Worker
64*333d2b36SAndroid Build Coastguard Worker// REParams holds information pertinent to the remote execution of a rule.
65*333d2b36SAndroid Build Coastguard Workertype REParams struct {
66*333d2b36SAndroid Build Coastguard Worker	// Platform is the key value pair used for remotely executing the action.
67*333d2b36SAndroid Build Coastguard Worker	Platform map[string]string
68*333d2b36SAndroid Build Coastguard Worker	// Labels is a map of labels that identify the rule.
69*333d2b36SAndroid Build Coastguard Worker	Labels map[string]string
70*333d2b36SAndroid Build Coastguard Worker	// ExecStrategy is the remote execution strategy: remote, local, or remote_local_fallback.
71*333d2b36SAndroid Build Coastguard Worker	ExecStrategy string
72*333d2b36SAndroid Build Coastguard Worker	// Inputs is a list of input paths or ninja variables.
73*333d2b36SAndroid Build Coastguard Worker	Inputs []string
74*333d2b36SAndroid Build Coastguard Worker	// RSPFiles is the name of the files used by the rule as a placeholder for an rsp input.
75*333d2b36SAndroid Build Coastguard Worker	RSPFiles []string
76*333d2b36SAndroid Build Coastguard Worker	// OutputFiles is a list of output file paths or ninja variables as placeholders for rule
77*333d2b36SAndroid Build Coastguard Worker	// outputs.
78*333d2b36SAndroid Build Coastguard Worker	OutputFiles []string
79*333d2b36SAndroid Build Coastguard Worker	// OutputDirectories is a list of output directories or ninja variables as placeholders for
80*333d2b36SAndroid Build Coastguard Worker	// rule output directories.
81*333d2b36SAndroid Build Coastguard Worker	OutputDirectories []string
82*333d2b36SAndroid Build Coastguard Worker	// ToolchainInputs is a list of paths or ninja variables pointing to the location of
83*333d2b36SAndroid Build Coastguard Worker	// toolchain binaries used by the rule.
84*333d2b36SAndroid Build Coastguard Worker	ToolchainInputs []string
85*333d2b36SAndroid Build Coastguard Worker	// EnvironmentVariables is a list of environment variables whose values should be passed through
86*333d2b36SAndroid Build Coastguard Worker	// to the remote execution.
87*333d2b36SAndroid Build Coastguard Worker	EnvironmentVariables []string
88*333d2b36SAndroid Build Coastguard Worker	// Boolean indicating whether to compare chosen exec strategy with local execution.
89*333d2b36SAndroid Build Coastguard Worker	Compare bool
90*333d2b36SAndroid Build Coastguard Worker	// Number of times the action should be rerun locally.
91*333d2b36SAndroid Build Coastguard Worker	NumLocalRuns int
92*333d2b36SAndroid Build Coastguard Worker	// Number of times the action should be rerun remotely.
93*333d2b36SAndroid Build Coastguard Worker	NumRemoteRuns int
94*333d2b36SAndroid Build Coastguard Worker	// Boolean indicating whether to update remote cache entry. Rewrapper defaults to true, so the name is negated here.
95*333d2b36SAndroid Build Coastguard Worker	NoRemoteUpdateCache bool
96*333d2b36SAndroid Build Coastguard Worker}
97*333d2b36SAndroid Build Coastguard Worker
98*333d2b36SAndroid Build Coastguard Workerfunc init() {
99*333d2b36SAndroid Build Coastguard Worker}
100*333d2b36SAndroid Build Coastguard Worker
101*333d2b36SAndroid Build Coastguard Worker// Template generates the remote execution wrapper template to be added as a prefix to the rule's
102*333d2b36SAndroid Build Coastguard Worker// command.
103*333d2b36SAndroid Build Coastguard Workerfunc (r *REParams) Template() string {
104*333d2b36SAndroid Build Coastguard Worker	return "${android.RBEWrapper}" + r.wrapperArgs()
105*333d2b36SAndroid Build Coastguard Worker}
106*333d2b36SAndroid Build Coastguard Worker
107*333d2b36SAndroid Build Coastguard Worker// NoVarTemplate generates the remote execution wrapper template without variables, to be used in
108*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.
109*333d2b36SAndroid Build Coastguard Workerfunc (r *REParams) NoVarTemplate(wrapper string) string {
110*333d2b36SAndroid Build Coastguard Worker	return wrapper + r.wrapperArgs()
111*333d2b36SAndroid Build Coastguard Worker}
112*333d2b36SAndroid Build Coastguard Worker
113*333d2b36SAndroid Build Coastguard Workerfunc (r *REParams) wrapperArgs() string {
114*333d2b36SAndroid Build Coastguard Worker	args := ""
115*333d2b36SAndroid Build Coastguard Worker	var kvs []string
116*333d2b36SAndroid Build Coastguard Worker	labels := r.Labels
117*333d2b36SAndroid Build Coastguard Worker	if len(labels) == 0 {
118*333d2b36SAndroid Build Coastguard Worker		labels = defaultLabels
119*333d2b36SAndroid Build Coastguard Worker	}
120*333d2b36SAndroid Build Coastguard Worker	for k, v := range labels {
121*333d2b36SAndroid Build Coastguard Worker		kvs = append(kvs, k+"="+v)
122*333d2b36SAndroid Build Coastguard Worker	}
123*333d2b36SAndroid Build Coastguard Worker	sort.Strings(kvs)
124*333d2b36SAndroid Build Coastguard Worker	args += " --labels=" + strings.Join(kvs, ",")
125*333d2b36SAndroid Build Coastguard Worker
126*333d2b36SAndroid Build Coastguard Worker	var platform []string
127*333d2b36SAndroid Build Coastguard Worker	for k, v := range r.Platform {
128*333d2b36SAndroid Build Coastguard Worker		if v == "" {
129*333d2b36SAndroid Build Coastguard Worker			continue
130*333d2b36SAndroid Build Coastguard Worker		}
131*333d2b36SAndroid Build Coastguard Worker		platform = append(platform, k+"="+v)
132*333d2b36SAndroid Build Coastguard Worker	}
133*333d2b36SAndroid Build Coastguard Worker	if _, ok := r.Platform[ContainerImageKey]; !ok {
134*333d2b36SAndroid Build Coastguard Worker		platform = append(platform, ContainerImageKey+"="+DefaultImage)
135*333d2b36SAndroid Build Coastguard Worker	}
136*333d2b36SAndroid Build Coastguard Worker	if platform != nil {
137*333d2b36SAndroid Build Coastguard Worker		sort.Strings(platform)
138*333d2b36SAndroid Build Coastguard Worker		args += " --platform=\"" + strings.Join(platform, ",") + "\""
139*333d2b36SAndroid Build Coastguard Worker	}
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Worker	strategy := r.ExecStrategy
142*333d2b36SAndroid Build Coastguard Worker	if strategy == "" {
143*333d2b36SAndroid Build Coastguard Worker		strategy = defaultExecStrategy
144*333d2b36SAndroid Build Coastguard Worker	}
145*333d2b36SAndroid Build Coastguard Worker	args += " --exec_strategy=" + strategy
146*333d2b36SAndroid Build Coastguard Worker
147*333d2b36SAndroid Build Coastguard Worker	if r.Compare && r.NumLocalRuns >= 0 && r.NumRemoteRuns >= 0 {
148*333d2b36SAndroid Build Coastguard Worker		args += fmt.Sprintf(" --compare=true --num_local_reruns=%d --num_remote_reruns=%d", r.NumLocalRuns, r.NumRemoteRuns)
149*333d2b36SAndroid Build Coastguard Worker	}
150*333d2b36SAndroid Build Coastguard Worker
151*333d2b36SAndroid Build Coastguard Worker	if r.NoRemoteUpdateCache {
152*333d2b36SAndroid Build Coastguard Worker		args += " --remote_update_cache=false"
153*333d2b36SAndroid Build Coastguard Worker	}
154*333d2b36SAndroid Build Coastguard Worker
155*333d2b36SAndroid Build Coastguard Worker	if len(r.Inputs) > 0 {
156*333d2b36SAndroid Build Coastguard Worker		args += " --inputs=" + strings.Join(r.Inputs, ",")
157*333d2b36SAndroid Build Coastguard Worker	}
158*333d2b36SAndroid Build Coastguard Worker
159*333d2b36SAndroid Build Coastguard Worker	if len(r.RSPFiles) > 0 {
160*333d2b36SAndroid Build Coastguard Worker		args += " --input_list_paths=" + strings.Join(r.RSPFiles, ",")
161*333d2b36SAndroid Build Coastguard Worker	}
162*333d2b36SAndroid Build Coastguard Worker
163*333d2b36SAndroid Build Coastguard Worker	if len(r.OutputFiles) > 0 {
164*333d2b36SAndroid Build Coastguard Worker		args += " --output_files=" + strings.Join(r.OutputFiles, ",")
165*333d2b36SAndroid Build Coastguard Worker	}
166*333d2b36SAndroid Build Coastguard Worker
167*333d2b36SAndroid Build Coastguard Worker	if len(r.OutputDirectories) > 0 {
168*333d2b36SAndroid Build Coastguard Worker		args += " --output_directories=" + strings.Join(r.OutputDirectories, ",")
169*333d2b36SAndroid Build Coastguard Worker	}
170*333d2b36SAndroid Build Coastguard Worker
171*333d2b36SAndroid Build Coastguard Worker	if len(r.ToolchainInputs) > 0 {
172*333d2b36SAndroid Build Coastguard Worker		args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
173*333d2b36SAndroid Build Coastguard Worker	}
174*333d2b36SAndroid Build Coastguard Worker
175*333d2b36SAndroid Build Coastguard Worker	envVarAllowlist := append(r.EnvironmentVariables, defaultEnvironmentVariables...)
176*333d2b36SAndroid Build Coastguard Worker
177*333d2b36SAndroid Build Coastguard Worker	if len(envVarAllowlist) > 0 {
178*333d2b36SAndroid Build Coastguard Worker		args += " --env_var_allowlist=" + strings.Join(envVarAllowlist, ",")
179*333d2b36SAndroid Build Coastguard Worker	}
180*333d2b36SAndroid Build Coastguard Worker
181*333d2b36SAndroid Build Coastguard Worker	return args + " -- "
182*333d2b36SAndroid Build Coastguard Worker}
183