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