1*333d2b36SAndroid Build Coastguard Worker// Copyright 2018 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 android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "crypto/sha256" 19*333d2b36SAndroid Build Coastguard Worker "fmt" 20*333d2b36SAndroid Build Coastguard Worker "path/filepath" 21*333d2b36SAndroid Build Coastguard Worker "sort" 22*333d2b36SAndroid Build Coastguard Worker "strings" 23*333d2b36SAndroid Build Coastguard Worker "testing" 24*333d2b36SAndroid Build Coastguard Worker 25*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 26*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 27*333d2b36SAndroid Build Coastguard Worker "google.golang.org/protobuf/encoding/prototext" 28*333d2b36SAndroid Build Coastguard Worker "google.golang.org/protobuf/proto" 29*333d2b36SAndroid Build Coastguard Worker 30*333d2b36SAndroid Build Coastguard Worker "android/soong/cmd/sbox/sbox_proto" 31*333d2b36SAndroid Build Coastguard Worker "android/soong/remoteexec" 32*333d2b36SAndroid Build Coastguard Worker "android/soong/response" 33*333d2b36SAndroid Build Coastguard Worker "android/soong/shared" 34*333d2b36SAndroid Build Coastguard Worker) 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workerconst sboxSandboxBaseDir = "__SBOX_SANDBOX_DIR__" 37*333d2b36SAndroid Build Coastguard Workerconst sboxOutSubDir = "out" 38*333d2b36SAndroid Build Coastguard Workerconst sboxToolsSubDir = "tools" 39*333d2b36SAndroid Build Coastguard Workerconst sboxOutDir = sboxSandboxBaseDir + "/" + sboxOutSubDir 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Workerconst nsjailToolsSubDir = "tools" 42*333d2b36SAndroid Build Coastguard Workerconst nsjailOutDir = "out" 43*333d2b36SAndroid Build Coastguard Worker 44*333d2b36SAndroid Build Coastguard Worker// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build 45*333d2b36SAndroid Build Coastguard Worker// graph. 46*333d2b36SAndroid Build Coastguard Workertype RuleBuilder struct { 47*333d2b36SAndroid Build Coastguard Worker pctx PackageContext 48*333d2b36SAndroid Build Coastguard Worker ctx BuilderContext 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Worker commands []*RuleBuilderCommand 51*333d2b36SAndroid Build Coastguard Worker installs RuleBuilderInstalls 52*333d2b36SAndroid Build Coastguard Worker temporariesSet map[WritablePath]bool 53*333d2b36SAndroid Build Coastguard Worker restat bool 54*333d2b36SAndroid Build Coastguard Worker sbox bool 55*333d2b36SAndroid Build Coastguard Worker highmem bool 56*333d2b36SAndroid Build Coastguard Worker remoteable RemoteRuleSupports 57*333d2b36SAndroid Build Coastguard Worker rbeParams *remoteexec.REParams 58*333d2b36SAndroid Build Coastguard Worker outDir WritablePath 59*333d2b36SAndroid Build Coastguard Worker sboxOutSubDir string 60*333d2b36SAndroid Build Coastguard Worker sboxTools bool 61*333d2b36SAndroid Build Coastguard Worker sboxInputs bool 62*333d2b36SAndroid Build Coastguard Worker sboxManifestPath WritablePath 63*333d2b36SAndroid Build Coastguard Worker missingDeps []string 64*333d2b36SAndroid Build Coastguard Worker args map[string]string 65*333d2b36SAndroid Build Coastguard Worker nsjail bool 66*333d2b36SAndroid Build Coastguard Worker nsjailKeepGendir bool 67*333d2b36SAndroid Build Coastguard Worker nsjailBasePath WritablePath 68*333d2b36SAndroid Build Coastguard Worker nsjailImplicits Paths 69*333d2b36SAndroid Build Coastguard Worker} 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker// NewRuleBuilder returns a newly created RuleBuilder. 72*333d2b36SAndroid Build Coastguard Workerfunc NewRuleBuilder(pctx PackageContext, ctx BuilderContext) *RuleBuilder { 73*333d2b36SAndroid Build Coastguard Worker return &RuleBuilder{ 74*333d2b36SAndroid Build Coastguard Worker pctx: pctx, 75*333d2b36SAndroid Build Coastguard Worker ctx: ctx, 76*333d2b36SAndroid Build Coastguard Worker temporariesSet: make(map[WritablePath]bool), 77*333d2b36SAndroid Build Coastguard Worker sboxOutSubDir: sboxOutSubDir, 78*333d2b36SAndroid Build Coastguard Worker } 79*333d2b36SAndroid Build Coastguard Worker} 80*333d2b36SAndroid Build Coastguard Worker 81*333d2b36SAndroid Build Coastguard Worker// SetSboxOutDirDirAsEmpty sets the out subdirectory to an empty string 82*333d2b36SAndroid Build Coastguard Worker// This is useful for sandboxing actions that change the execution root to a path in out/ (e.g mixed builds) 83*333d2b36SAndroid Build Coastguard Worker// For such actions, SetSboxOutDirDirAsEmpty ensures that the path does not become $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/... 84*333d2b36SAndroid Build Coastguard Workerfunc (rb *RuleBuilder) SetSboxOutDirDirAsEmpty() *RuleBuilder { 85*333d2b36SAndroid Build Coastguard Worker rb.sboxOutSubDir = "" 86*333d2b36SAndroid Build Coastguard Worker return rb 87*333d2b36SAndroid Build Coastguard Worker} 88*333d2b36SAndroid Build Coastguard Worker 89*333d2b36SAndroid Build Coastguard Worker// Set the phony_output argument. 90*333d2b36SAndroid Build Coastguard Worker// This causes the output files to be ignored. 91*333d2b36SAndroid Build Coastguard Worker// If the output isn't created, it's not treated as an error. 92*333d2b36SAndroid Build Coastguard Worker// The build rule is run every time whether or not the output is created. 93*333d2b36SAndroid Build Coastguard Workerfunc (rb *RuleBuilder) SetPhonyOutput() { 94*333d2b36SAndroid Build Coastguard Worker if rb.args == nil { 95*333d2b36SAndroid Build Coastguard Worker rb.args = make(map[string]string) 96*333d2b36SAndroid Build Coastguard Worker } 97*333d2b36SAndroid Build Coastguard Worker rb.args["phony_output"] = "true" 98*333d2b36SAndroid Build Coastguard Worker} 99*333d2b36SAndroid Build Coastguard Worker 100*333d2b36SAndroid Build Coastguard Worker// RuleBuilderInstall is a tuple of install from and to locations. 101*333d2b36SAndroid Build Coastguard Workertype RuleBuilderInstall struct { 102*333d2b36SAndroid Build Coastguard Worker From Path 103*333d2b36SAndroid Build Coastguard Worker To string 104*333d2b36SAndroid Build Coastguard Worker} 105*333d2b36SAndroid Build Coastguard Worker 106*333d2b36SAndroid Build Coastguard Workertype RuleBuilderInstalls []RuleBuilderInstall 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker// String returns the RuleBuilderInstalls in the form used by $(call copy-many-files) in Make, a space separated 109*333d2b36SAndroid Build Coastguard Worker// list of from:to tuples. 110*333d2b36SAndroid Build Coastguard Workerfunc (installs RuleBuilderInstalls) String() string { 111*333d2b36SAndroid Build Coastguard Worker sb := strings.Builder{} 112*333d2b36SAndroid Build Coastguard Worker for i, install := range installs { 113*333d2b36SAndroid Build Coastguard Worker if i != 0 { 114*333d2b36SAndroid Build Coastguard Worker sb.WriteRune(' ') 115*333d2b36SAndroid Build Coastguard Worker } 116*333d2b36SAndroid Build Coastguard Worker sb.WriteString(install.From.String()) 117*333d2b36SAndroid Build Coastguard Worker sb.WriteRune(':') 118*333d2b36SAndroid Build Coastguard Worker sb.WriteString(install.To) 119*333d2b36SAndroid Build Coastguard Worker } 120*333d2b36SAndroid Build Coastguard Worker return sb.String() 121*333d2b36SAndroid Build Coastguard Worker} 122*333d2b36SAndroid Build Coastguard Worker 123*333d2b36SAndroid Build Coastguard Worker// MissingDeps adds modules to the list of missing dependencies. If MissingDeps 124*333d2b36SAndroid Build Coastguard Worker// is called with a non-empty input, any call to Build will result in a rule 125*333d2b36SAndroid Build Coastguard Worker// that will print an error listing the missing dependencies and fail. 126*333d2b36SAndroid Build Coastguard Worker// MissingDeps should only be called if Config.AllowMissingDependencies() is 127*333d2b36SAndroid Build Coastguard Worker// true. 128*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) MissingDeps(missingDeps []string) { 129*333d2b36SAndroid Build Coastguard Worker r.missingDeps = append(r.missingDeps, missingDeps...) 130*333d2b36SAndroid Build Coastguard Worker} 131*333d2b36SAndroid Build Coastguard Worker 132*333d2b36SAndroid Build Coastguard Worker// Restat marks the rule as a restat rule, which will be passed to ModuleContext.Rule in BuildParams.Restat. 133*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Restat() *RuleBuilder { 134*333d2b36SAndroid Build Coastguard Worker r.restat = true 135*333d2b36SAndroid Build Coastguard Worker return r 136*333d2b36SAndroid Build Coastguard Worker} 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker// HighMem marks the rule as a high memory rule, which will limit how many run in parallel with other high memory 139*333d2b36SAndroid Build Coastguard Worker// rules. 140*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) HighMem() *RuleBuilder { 141*333d2b36SAndroid Build Coastguard Worker r.highmem = true 142*333d2b36SAndroid Build Coastguard Worker return r 143*333d2b36SAndroid Build Coastguard Worker} 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Worker// Remoteable marks the rule as supporting remote execution. 146*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Remoteable(supports RemoteRuleSupports) *RuleBuilder { 147*333d2b36SAndroid Build Coastguard Worker r.remoteable = supports 148*333d2b36SAndroid Build Coastguard Worker return r 149*333d2b36SAndroid Build Coastguard Worker} 150*333d2b36SAndroid Build Coastguard Worker 151*333d2b36SAndroid Build Coastguard Worker// Rewrapper marks the rule as running inside rewrapper using the given params in order to support 152*333d2b36SAndroid Build Coastguard Worker// running on RBE. During RuleBuilder.Build the params will be combined with the inputs, outputs 153*333d2b36SAndroid Build Coastguard Worker// and tools known to RuleBuilder to prepend an appropriate rewrapper command line to the rule's 154*333d2b36SAndroid Build Coastguard Worker// command line. 155*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Rewrapper(params *remoteexec.REParams) *RuleBuilder { 156*333d2b36SAndroid Build Coastguard Worker if !r.sboxInputs { 157*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("RuleBuilder.Rewrapper must be called after RuleBuilder.SandboxInputs")) 158*333d2b36SAndroid Build Coastguard Worker } 159*333d2b36SAndroid Build Coastguard Worker r.rbeParams = params 160*333d2b36SAndroid Build Coastguard Worker return r 161*333d2b36SAndroid Build Coastguard Worker} 162*333d2b36SAndroid Build Coastguard Worker 163*333d2b36SAndroid Build Coastguard Worker// Sbox marks the rule as needing to be wrapped by sbox. The outputDir should point to the output 164*333d2b36SAndroid Build Coastguard Worker// directory that sbox will wipe. It should not be written to by any other rule. manifestPath should 165*333d2b36SAndroid Build Coastguard Worker// point to a location where sbox's manifest will be written and must be outside outputDir. sbox 166*333d2b36SAndroid Build Coastguard Worker// will ensure that all outputs have been written, and will discard any output files that were not 167*333d2b36SAndroid Build Coastguard Worker// specified. 168*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Sbox(outputDir WritablePath, manifestPath WritablePath) *RuleBuilder { 169*333d2b36SAndroid Build Coastguard Worker if r.sbox { 170*333d2b36SAndroid Build Coastguard Worker panic("Sbox() may not be called more than once") 171*333d2b36SAndroid Build Coastguard Worker } 172*333d2b36SAndroid Build Coastguard Worker if len(r.commands) > 0 { 173*333d2b36SAndroid Build Coastguard Worker panic("Sbox() may not be called after Command()") 174*333d2b36SAndroid Build Coastguard Worker } 175*333d2b36SAndroid Build Coastguard Worker if r.nsjail { 176*333d2b36SAndroid Build Coastguard Worker panic("Sbox() may not be called after Nsjail()") 177*333d2b36SAndroid Build Coastguard Worker } 178*333d2b36SAndroid Build Coastguard Worker r.sbox = true 179*333d2b36SAndroid Build Coastguard Worker r.outDir = outputDir 180*333d2b36SAndroid Build Coastguard Worker r.sboxManifestPath = manifestPath 181*333d2b36SAndroid Build Coastguard Worker return r 182*333d2b36SAndroid Build Coastguard Worker} 183*333d2b36SAndroid Build Coastguard Worker 184*333d2b36SAndroid Build Coastguard Worker// Nsjail marks the rule as needing to be wrapped by nsjail. The outputDir should point to the 185*333d2b36SAndroid Build Coastguard Worker// output directory that nsjail will mount to out/. It should not be written to by any other rule. 186*333d2b36SAndroid Build Coastguard Worker// baseDir should point to a location where nsjail will mount to /nsjail_build_sandbox, which will 187*333d2b36SAndroid Build Coastguard Worker// be the working directory of the command. 188*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Nsjail(outputDir WritablePath, baseDir WritablePath) *RuleBuilder { 189*333d2b36SAndroid Build Coastguard Worker if len(r.commands) > 0 { 190*333d2b36SAndroid Build Coastguard Worker panic("Nsjail() may not be called after Command()") 191*333d2b36SAndroid Build Coastguard Worker } 192*333d2b36SAndroid Build Coastguard Worker if r.sbox { 193*333d2b36SAndroid Build Coastguard Worker panic("Nsjail() may not be called after Sbox()") 194*333d2b36SAndroid Build Coastguard Worker } 195*333d2b36SAndroid Build Coastguard Worker r.nsjail = true 196*333d2b36SAndroid Build Coastguard Worker r.outDir = outputDir 197*333d2b36SAndroid Build Coastguard Worker r.nsjailBasePath = baseDir 198*333d2b36SAndroid Build Coastguard Worker return r 199*333d2b36SAndroid Build Coastguard Worker} 200*333d2b36SAndroid Build Coastguard Worker 201*333d2b36SAndroid Build Coastguard Worker// NsjailImplicits adds implicit inputs that are not directly mounted. This is useful when 202*333d2b36SAndroid Build Coastguard Worker// the rule mounts directories, as files within those directories can be globbed and 203*333d2b36SAndroid Build Coastguard Worker// tracked as dependencies with NsjailImplicits(). 204*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) NsjailImplicits(inputs Paths) *RuleBuilder { 205*333d2b36SAndroid Build Coastguard Worker if !r.nsjail { 206*333d2b36SAndroid Build Coastguard Worker panic("NsjailImplicits() must be called after Nsjail()") 207*333d2b36SAndroid Build Coastguard Worker } 208*333d2b36SAndroid Build Coastguard Worker r.nsjailImplicits = append(r.nsjailImplicits, inputs...) 209*333d2b36SAndroid Build Coastguard Worker return r 210*333d2b36SAndroid Build Coastguard Worker} 211*333d2b36SAndroid Build Coastguard Worker 212*333d2b36SAndroid Build Coastguard Worker// By default, nsjail rules truncate outputDir and baseDir before running commands, similar to Sbox 213*333d2b36SAndroid Build Coastguard Worker// rules which always run commands in a fresh sandbox. Calling NsjailKeepGendir keeps outputDir and 214*333d2b36SAndroid Build Coastguard Worker// baseDir as-is, leaving previous artifacts. This is useful when the rules support incremental 215*333d2b36SAndroid Build Coastguard Worker// builds. 216*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) NsjailKeepGendir() *RuleBuilder { 217*333d2b36SAndroid Build Coastguard Worker if !r.nsjail { 218*333d2b36SAndroid Build Coastguard Worker panic("NsjailKeepGendir() must be called after Nsjail()") 219*333d2b36SAndroid Build Coastguard Worker } 220*333d2b36SAndroid Build Coastguard Worker r.nsjailKeepGendir = true 221*333d2b36SAndroid Build Coastguard Worker return r 222*333d2b36SAndroid Build Coastguard Worker} 223*333d2b36SAndroid Build Coastguard Worker 224*333d2b36SAndroid Build Coastguard Worker// SandboxTools enables tool sandboxing for the rule by copying any referenced tools into the 225*333d2b36SAndroid Build Coastguard Worker// sandbox. 226*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) SandboxTools() *RuleBuilder { 227*333d2b36SAndroid Build Coastguard Worker if !r.sbox { 228*333d2b36SAndroid Build Coastguard Worker panic("SandboxTools() must be called after Sbox()") 229*333d2b36SAndroid Build Coastguard Worker } 230*333d2b36SAndroid Build Coastguard Worker if len(r.commands) > 0 { 231*333d2b36SAndroid Build Coastguard Worker panic("SandboxTools() may not be called after Command()") 232*333d2b36SAndroid Build Coastguard Worker } 233*333d2b36SAndroid Build Coastguard Worker r.sboxTools = true 234*333d2b36SAndroid Build Coastguard Worker return r 235*333d2b36SAndroid Build Coastguard Worker} 236*333d2b36SAndroid Build Coastguard Worker 237*333d2b36SAndroid Build Coastguard Worker// SandboxInputs enables input sandboxing for the rule by copying any referenced inputs into the 238*333d2b36SAndroid Build Coastguard Worker// sandbox. It also implies SandboxTools(). 239*333d2b36SAndroid Build Coastguard Worker// 240*333d2b36SAndroid Build Coastguard Worker// Sandboxing inputs requires RuleBuilder to be aware of all references to input paths. Paths 241*333d2b36SAndroid Build Coastguard Worker// that are passed to RuleBuilder outside of the methods that expect inputs, for example 242*333d2b36SAndroid Build Coastguard Worker// FlagWithArg, must use RuleBuilderCommand.PathForInput to translate the path to one that matches 243*333d2b36SAndroid Build Coastguard Worker// the sandbox layout. 244*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) SandboxInputs() *RuleBuilder { 245*333d2b36SAndroid Build Coastguard Worker if !r.sbox { 246*333d2b36SAndroid Build Coastguard Worker panic("SandboxInputs() must be called after Sbox()") 247*333d2b36SAndroid Build Coastguard Worker } 248*333d2b36SAndroid Build Coastguard Worker if len(r.commands) > 0 { 249*333d2b36SAndroid Build Coastguard Worker panic("SandboxInputs() may not be called after Command()") 250*333d2b36SAndroid Build Coastguard Worker } 251*333d2b36SAndroid Build Coastguard Worker r.sboxTools = true 252*333d2b36SAndroid Build Coastguard Worker r.sboxInputs = true 253*333d2b36SAndroid Build Coastguard Worker return r 254*333d2b36SAndroid Build Coastguard Worker} 255*333d2b36SAndroid Build Coastguard Worker 256*333d2b36SAndroid Build Coastguard Worker// Install associates an output of the rule with an install location, which can be retrieved later using 257*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Installs. 258*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Install(from Path, to string) { 259*333d2b36SAndroid Build Coastguard Worker r.installs = append(r.installs, RuleBuilderInstall{from, to}) 260*333d2b36SAndroid Build Coastguard Worker} 261*333d2b36SAndroid Build Coastguard Worker 262*333d2b36SAndroid Build Coastguard Worker// Command returns a new RuleBuilderCommand for the rule. The commands will be ordered in the rule by when they were 263*333d2b36SAndroid Build Coastguard Worker// created by this method. That can be mutated through their methods in any order, as long as the mutations do not 264*333d2b36SAndroid Build Coastguard Worker// race with any call to Build. 265*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Command() *RuleBuilderCommand { 266*333d2b36SAndroid Build Coastguard Worker command := &RuleBuilderCommand{ 267*333d2b36SAndroid Build Coastguard Worker rule: r, 268*333d2b36SAndroid Build Coastguard Worker } 269*333d2b36SAndroid Build Coastguard Worker r.commands = append(r.commands, command) 270*333d2b36SAndroid Build Coastguard Worker return command 271*333d2b36SAndroid Build Coastguard Worker} 272*333d2b36SAndroid Build Coastguard Worker 273*333d2b36SAndroid Build Coastguard Worker// Temporary marks an output of a command as an intermediate file that will be used as an input to another command 274*333d2b36SAndroid Build Coastguard Worker// in the same rule, and should not be listed in Outputs. 275*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Temporary(path WritablePath) { 276*333d2b36SAndroid Build Coastguard Worker r.temporariesSet[path] = true 277*333d2b36SAndroid Build Coastguard Worker} 278*333d2b36SAndroid Build Coastguard Worker 279*333d2b36SAndroid Build Coastguard Worker// DeleteTemporaryFiles adds a command to the rule that deletes any outputs that have been marked using Temporary 280*333d2b36SAndroid Build Coastguard Worker// when the rule runs. DeleteTemporaryFiles should be called after all calls to Temporary. 281*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) DeleteTemporaryFiles() { 282*333d2b36SAndroid Build Coastguard Worker var temporariesList WritablePaths 283*333d2b36SAndroid Build Coastguard Worker 284*333d2b36SAndroid Build Coastguard Worker for intermediate := range r.temporariesSet { 285*333d2b36SAndroid Build Coastguard Worker temporariesList = append(temporariesList, intermediate) 286*333d2b36SAndroid Build Coastguard Worker } 287*333d2b36SAndroid Build Coastguard Worker 288*333d2b36SAndroid Build Coastguard Worker sort.Slice(temporariesList, func(i, j int) bool { 289*333d2b36SAndroid Build Coastguard Worker return temporariesList[i].String() < temporariesList[j].String() 290*333d2b36SAndroid Build Coastguard Worker }) 291*333d2b36SAndroid Build Coastguard Worker 292*333d2b36SAndroid Build Coastguard Worker r.Command().Text("rm").Flag("-f").Outputs(temporariesList) 293*333d2b36SAndroid Build Coastguard Worker} 294*333d2b36SAndroid Build Coastguard Worker 295*333d2b36SAndroid Build Coastguard Worker// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take 296*333d2b36SAndroid Build Coastguard Worker// input paths, such as RuleBuilderCommand.Input, RuleBuilderCommand.Implicit, or 297*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand.FlagWithInput. Inputs to a command that are also outputs of another command 298*333d2b36SAndroid Build Coastguard Worker// in the same RuleBuilder are filtered out. The list is sorted and duplicates removed. 299*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Inputs() Paths { 300*333d2b36SAndroid Build Coastguard Worker outputs := r.outputSet() 301*333d2b36SAndroid Build Coastguard Worker depFiles := r.depFileSet() 302*333d2b36SAndroid Build Coastguard Worker 303*333d2b36SAndroid Build Coastguard Worker inputs := make(map[string]Path) 304*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 305*333d2b36SAndroid Build Coastguard Worker for _, input := range append(c.inputs, c.implicits...) { 306*333d2b36SAndroid Build Coastguard Worker inputStr := input.String() 307*333d2b36SAndroid Build Coastguard Worker if _, isOutput := outputs[inputStr]; !isOutput { 308*333d2b36SAndroid Build Coastguard Worker if _, isDepFile := depFiles[inputStr]; !isDepFile { 309*333d2b36SAndroid Build Coastguard Worker inputs[input.String()] = input 310*333d2b36SAndroid Build Coastguard Worker } 311*333d2b36SAndroid Build Coastguard Worker } 312*333d2b36SAndroid Build Coastguard Worker } 313*333d2b36SAndroid Build Coastguard Worker } 314*333d2b36SAndroid Build Coastguard Worker 315*333d2b36SAndroid Build Coastguard Worker var inputList Paths 316*333d2b36SAndroid Build Coastguard Worker for _, input := range inputs { 317*333d2b36SAndroid Build Coastguard Worker inputList = append(inputList, input) 318*333d2b36SAndroid Build Coastguard Worker } 319*333d2b36SAndroid Build Coastguard Worker 320*333d2b36SAndroid Build Coastguard Worker sort.Slice(inputList, func(i, j int) bool { 321*333d2b36SAndroid Build Coastguard Worker return inputList[i].String() < inputList[j].String() 322*333d2b36SAndroid Build Coastguard Worker }) 323*333d2b36SAndroid Build Coastguard Worker 324*333d2b36SAndroid Build Coastguard Worker return inputList 325*333d2b36SAndroid Build Coastguard Worker} 326*333d2b36SAndroid Build Coastguard Worker 327*333d2b36SAndroid Build Coastguard Worker// OrderOnlys returns the list of paths that were passed to the RuleBuilderCommand.OrderOnly or 328*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand.OrderOnlys. The list is sorted and duplicates removed. 329*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) OrderOnlys() Paths { 330*333d2b36SAndroid Build Coastguard Worker orderOnlys := make(map[string]Path) 331*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 332*333d2b36SAndroid Build Coastguard Worker for _, orderOnly := range c.orderOnlys { 333*333d2b36SAndroid Build Coastguard Worker orderOnlys[orderOnly.String()] = orderOnly 334*333d2b36SAndroid Build Coastguard Worker } 335*333d2b36SAndroid Build Coastguard Worker } 336*333d2b36SAndroid Build Coastguard Worker 337*333d2b36SAndroid Build Coastguard Worker var orderOnlyList Paths 338*333d2b36SAndroid Build Coastguard Worker for _, orderOnly := range orderOnlys { 339*333d2b36SAndroid Build Coastguard Worker orderOnlyList = append(orderOnlyList, orderOnly) 340*333d2b36SAndroid Build Coastguard Worker } 341*333d2b36SAndroid Build Coastguard Worker 342*333d2b36SAndroid Build Coastguard Worker sort.Slice(orderOnlyList, func(i, j int) bool { 343*333d2b36SAndroid Build Coastguard Worker return orderOnlyList[i].String() < orderOnlyList[j].String() 344*333d2b36SAndroid Build Coastguard Worker }) 345*333d2b36SAndroid Build Coastguard Worker 346*333d2b36SAndroid Build Coastguard Worker return orderOnlyList 347*333d2b36SAndroid Build Coastguard Worker} 348*333d2b36SAndroid Build Coastguard Worker 349*333d2b36SAndroid Build Coastguard Worker// Validations returns the list of paths that were passed to RuleBuilderCommand.Validation or 350*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand.Validations. The list is sorted and duplicates removed. 351*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Validations() Paths { 352*333d2b36SAndroid Build Coastguard Worker validations := make(map[string]Path) 353*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 354*333d2b36SAndroid Build Coastguard Worker for _, validation := range c.validations { 355*333d2b36SAndroid Build Coastguard Worker validations[validation.String()] = validation 356*333d2b36SAndroid Build Coastguard Worker } 357*333d2b36SAndroid Build Coastguard Worker } 358*333d2b36SAndroid Build Coastguard Worker 359*333d2b36SAndroid Build Coastguard Worker var validationList Paths 360*333d2b36SAndroid Build Coastguard Worker for _, validation := range validations { 361*333d2b36SAndroid Build Coastguard Worker validationList = append(validationList, validation) 362*333d2b36SAndroid Build Coastguard Worker } 363*333d2b36SAndroid Build Coastguard Worker 364*333d2b36SAndroid Build Coastguard Worker sort.Slice(validationList, func(i, j int) bool { 365*333d2b36SAndroid Build Coastguard Worker return validationList[i].String() < validationList[j].String() 366*333d2b36SAndroid Build Coastguard Worker }) 367*333d2b36SAndroid Build Coastguard Worker 368*333d2b36SAndroid Build Coastguard Worker return validationList 369*333d2b36SAndroid Build Coastguard Worker} 370*333d2b36SAndroid Build Coastguard Worker 371*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) outputSet() map[string]WritablePath { 372*333d2b36SAndroid Build Coastguard Worker outputs := make(map[string]WritablePath) 373*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 374*333d2b36SAndroid Build Coastguard Worker for _, output := range c.outputs { 375*333d2b36SAndroid Build Coastguard Worker outputs[output.String()] = output 376*333d2b36SAndroid Build Coastguard Worker } 377*333d2b36SAndroid Build Coastguard Worker } 378*333d2b36SAndroid Build Coastguard Worker return outputs 379*333d2b36SAndroid Build Coastguard Worker} 380*333d2b36SAndroid Build Coastguard Worker 381*333d2b36SAndroid Build Coastguard Worker// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take 382*333d2b36SAndroid Build Coastguard Worker// output paths, such as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or 383*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand.FlagWithInput. The list is sorted and duplicates removed. 384*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Outputs() WritablePaths { 385*333d2b36SAndroid Build Coastguard Worker outputs := r.outputSet() 386*333d2b36SAndroid Build Coastguard Worker 387*333d2b36SAndroid Build Coastguard Worker var outputList WritablePaths 388*333d2b36SAndroid Build Coastguard Worker for _, output := range outputs { 389*333d2b36SAndroid Build Coastguard Worker if !r.temporariesSet[output] { 390*333d2b36SAndroid Build Coastguard Worker outputList = append(outputList, output) 391*333d2b36SAndroid Build Coastguard Worker } 392*333d2b36SAndroid Build Coastguard Worker } 393*333d2b36SAndroid Build Coastguard Worker 394*333d2b36SAndroid Build Coastguard Worker sort.Slice(outputList, func(i, j int) bool { 395*333d2b36SAndroid Build Coastguard Worker return outputList[i].String() < outputList[j].String() 396*333d2b36SAndroid Build Coastguard Worker }) 397*333d2b36SAndroid Build Coastguard Worker 398*333d2b36SAndroid Build Coastguard Worker return outputList 399*333d2b36SAndroid Build Coastguard Worker} 400*333d2b36SAndroid Build Coastguard Worker 401*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) depFileSet() map[string]WritablePath { 402*333d2b36SAndroid Build Coastguard Worker depFiles := make(map[string]WritablePath) 403*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 404*333d2b36SAndroid Build Coastguard Worker for _, depFile := range c.depFiles { 405*333d2b36SAndroid Build Coastguard Worker depFiles[depFile.String()] = depFile 406*333d2b36SAndroid Build Coastguard Worker } 407*333d2b36SAndroid Build Coastguard Worker } 408*333d2b36SAndroid Build Coastguard Worker return depFiles 409*333d2b36SAndroid Build Coastguard Worker} 410*333d2b36SAndroid Build Coastguard Worker 411*333d2b36SAndroid Build Coastguard Worker// DepFiles returns the list of paths that were passed to the RuleBuilderCommand methods that take depfile paths, such 412*333d2b36SAndroid Build Coastguard Worker// as RuleBuilderCommand.DepFile or RuleBuilderCommand.FlagWithDepFile. 413*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) DepFiles() WritablePaths { 414*333d2b36SAndroid Build Coastguard Worker var depFiles WritablePaths 415*333d2b36SAndroid Build Coastguard Worker 416*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 417*333d2b36SAndroid Build Coastguard Worker for _, depFile := range c.depFiles { 418*333d2b36SAndroid Build Coastguard Worker depFiles = append(depFiles, depFile) 419*333d2b36SAndroid Build Coastguard Worker } 420*333d2b36SAndroid Build Coastguard Worker } 421*333d2b36SAndroid Build Coastguard Worker 422*333d2b36SAndroid Build Coastguard Worker return depFiles 423*333d2b36SAndroid Build Coastguard Worker} 424*333d2b36SAndroid Build Coastguard Worker 425*333d2b36SAndroid Build Coastguard Worker// Installs returns the list of tuples passed to Install. 426*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Installs() RuleBuilderInstalls { 427*333d2b36SAndroid Build Coastguard Worker return append(RuleBuilderInstalls(nil), r.installs...) 428*333d2b36SAndroid Build Coastguard Worker} 429*333d2b36SAndroid Build Coastguard Worker 430*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) toolsSet() map[string]Path { 431*333d2b36SAndroid Build Coastguard Worker tools := make(map[string]Path) 432*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 433*333d2b36SAndroid Build Coastguard Worker for _, tool := range c.tools { 434*333d2b36SAndroid Build Coastguard Worker tools[tool.String()] = tool 435*333d2b36SAndroid Build Coastguard Worker } 436*333d2b36SAndroid Build Coastguard Worker } 437*333d2b36SAndroid Build Coastguard Worker 438*333d2b36SAndroid Build Coastguard Worker return tools 439*333d2b36SAndroid Build Coastguard Worker} 440*333d2b36SAndroid Build Coastguard Worker 441*333d2b36SAndroid Build Coastguard Worker// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method. The 442*333d2b36SAndroid Build Coastguard Worker// list is sorted and duplicates removed. 443*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Tools() Paths { 444*333d2b36SAndroid Build Coastguard Worker toolsSet := r.toolsSet() 445*333d2b36SAndroid Build Coastguard Worker 446*333d2b36SAndroid Build Coastguard Worker var toolsList Paths 447*333d2b36SAndroid Build Coastguard Worker for _, tool := range toolsSet { 448*333d2b36SAndroid Build Coastguard Worker toolsList = append(toolsList, tool) 449*333d2b36SAndroid Build Coastguard Worker } 450*333d2b36SAndroid Build Coastguard Worker 451*333d2b36SAndroid Build Coastguard Worker sort.Slice(toolsList, func(i, j int) bool { 452*333d2b36SAndroid Build Coastguard Worker return toolsList[i].String() < toolsList[j].String() 453*333d2b36SAndroid Build Coastguard Worker }) 454*333d2b36SAndroid Build Coastguard Worker 455*333d2b36SAndroid Build Coastguard Worker return toolsList 456*333d2b36SAndroid Build Coastguard Worker} 457*333d2b36SAndroid Build Coastguard Worker 458*333d2b36SAndroid Build Coastguard Worker// RspFileInputs returns the list of paths that were passed to the RuleBuilderCommand.FlagWithRspFileInputList method. 459*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) RspFileInputs() Paths { 460*333d2b36SAndroid Build Coastguard Worker var rspFileInputs Paths 461*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 462*333d2b36SAndroid Build Coastguard Worker for _, rspFile := range c.rspFiles { 463*333d2b36SAndroid Build Coastguard Worker rspFileInputs = append(rspFileInputs, rspFile.paths...) 464*333d2b36SAndroid Build Coastguard Worker } 465*333d2b36SAndroid Build Coastguard Worker } 466*333d2b36SAndroid Build Coastguard Worker 467*333d2b36SAndroid Build Coastguard Worker return rspFileInputs 468*333d2b36SAndroid Build Coastguard Worker} 469*333d2b36SAndroid Build Coastguard Worker 470*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) rspFiles() []rspFileAndPaths { 471*333d2b36SAndroid Build Coastguard Worker var rspFiles []rspFileAndPaths 472*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 473*333d2b36SAndroid Build Coastguard Worker rspFiles = append(rspFiles, c.rspFiles...) 474*333d2b36SAndroid Build Coastguard Worker } 475*333d2b36SAndroid Build Coastguard Worker 476*333d2b36SAndroid Build Coastguard Worker return rspFiles 477*333d2b36SAndroid Build Coastguard Worker} 478*333d2b36SAndroid Build Coastguard Worker 479*333d2b36SAndroid Build Coastguard Worker// Commands returns a slice containing the built command line for each call to RuleBuilder.Command. 480*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Commands() []string { 481*333d2b36SAndroid Build Coastguard Worker var commands []string 482*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 483*333d2b36SAndroid Build Coastguard Worker commands = append(commands, c.String()) 484*333d2b36SAndroid Build Coastguard Worker } 485*333d2b36SAndroid Build Coastguard Worker return commands 486*333d2b36SAndroid Build Coastguard Worker} 487*333d2b36SAndroid Build Coastguard Worker 488*333d2b36SAndroid Build Coastguard Worker// BuilderContext is a subset of ModuleContext and SingletonContext. 489*333d2b36SAndroid Build Coastguard Workertype BuilderContext interface { 490*333d2b36SAndroid Build Coastguard Worker PathContext 491*333d2b36SAndroid Build Coastguard Worker Rule(PackageContext, string, blueprint.RuleParams, ...string) blueprint.Rule 492*333d2b36SAndroid Build Coastguard Worker Build(PackageContext, BuildParams) 493*333d2b36SAndroid Build Coastguard Worker} 494*333d2b36SAndroid Build Coastguard Worker 495*333d2b36SAndroid Build Coastguard Workervar _ BuilderContext = ModuleContext(nil) 496*333d2b36SAndroid Build Coastguard Workervar _ BuilderContext = SingletonContext(nil) 497*333d2b36SAndroid Build Coastguard Worker 498*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) depFileMergerCmd(depFiles WritablePaths) *RuleBuilderCommand { 499*333d2b36SAndroid Build Coastguard Worker return r.Command(). 500*333d2b36SAndroid Build Coastguard Worker builtToolWithoutDeps("dep_fixer"). 501*333d2b36SAndroid Build Coastguard Worker Inputs(depFiles.Paths()) 502*333d2b36SAndroid Build Coastguard Worker} 503*333d2b36SAndroid Build Coastguard Worker 504*333d2b36SAndroid Build Coastguard Worker// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for 505*333d2b36SAndroid Build Coastguard Worker// Outputs. 506*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) Build(name string, desc string) { 507*333d2b36SAndroid Build Coastguard Worker r.build(name, desc) 508*333d2b36SAndroid Build Coastguard Worker} 509*333d2b36SAndroid Build Coastguard Worker 510*333d2b36SAndroid Build Coastguard Workervar sandboxEnvOnceKey = NewOnceKey("sandbox_environment_variables") 511*333d2b36SAndroid Build Coastguard Worker 512*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) build(name string, desc string) { 513*333d2b36SAndroid Build Coastguard Worker name = ninjaNameEscape(name) 514*333d2b36SAndroid Build Coastguard Worker 515*333d2b36SAndroid Build Coastguard Worker if len(r.missingDeps) > 0 { 516*333d2b36SAndroid Build Coastguard Worker r.ctx.Build(r.pctx, BuildParams{ 517*333d2b36SAndroid Build Coastguard Worker Rule: ErrorRule, 518*333d2b36SAndroid Build Coastguard Worker Outputs: r.Outputs(), 519*333d2b36SAndroid Build Coastguard Worker Description: desc, 520*333d2b36SAndroid Build Coastguard Worker Args: map[string]string{ 521*333d2b36SAndroid Build Coastguard Worker "error": "missing dependencies: " + strings.Join(r.missingDeps, ", "), 522*333d2b36SAndroid Build Coastguard Worker }, 523*333d2b36SAndroid Build Coastguard Worker }) 524*333d2b36SAndroid Build Coastguard Worker return 525*333d2b36SAndroid Build Coastguard Worker } 526*333d2b36SAndroid Build Coastguard Worker 527*333d2b36SAndroid Build Coastguard Worker var depFile WritablePath 528*333d2b36SAndroid Build Coastguard Worker var depFormat blueprint.Deps 529*333d2b36SAndroid Build Coastguard Worker if depFiles := r.DepFiles(); len(depFiles) > 0 { 530*333d2b36SAndroid Build Coastguard Worker depFile = depFiles[0] 531*333d2b36SAndroid Build Coastguard Worker depFormat = blueprint.DepsGCC 532*333d2b36SAndroid Build Coastguard Worker if len(depFiles) > 1 { 533*333d2b36SAndroid Build Coastguard Worker // Add a command locally that merges all depfiles together into the first depfile. 534*333d2b36SAndroid Build Coastguard Worker r.depFileMergerCmd(depFiles) 535*333d2b36SAndroid Build Coastguard Worker 536*333d2b36SAndroid Build Coastguard Worker if r.sbox { 537*333d2b36SAndroid Build Coastguard Worker // Check for Rel() errors, as all depfiles should be in the output dir. Errors 538*333d2b36SAndroid Build Coastguard Worker // will be reported to the ctx. 539*333d2b36SAndroid Build Coastguard Worker for _, path := range depFiles[1:] { 540*333d2b36SAndroid Build Coastguard Worker Rel(r.ctx, r.outDir.String(), path.String()) 541*333d2b36SAndroid Build Coastguard Worker } 542*333d2b36SAndroid Build Coastguard Worker } 543*333d2b36SAndroid Build Coastguard Worker } 544*333d2b36SAndroid Build Coastguard Worker } 545*333d2b36SAndroid Build Coastguard Worker 546*333d2b36SAndroid Build Coastguard Worker tools := r.Tools() 547*333d2b36SAndroid Build Coastguard Worker commands := r.Commands() 548*333d2b36SAndroid Build Coastguard Worker outputs := r.Outputs() 549*333d2b36SAndroid Build Coastguard Worker inputs := r.Inputs() 550*333d2b36SAndroid Build Coastguard Worker rspFiles := r.rspFiles() 551*333d2b36SAndroid Build Coastguard Worker 552*333d2b36SAndroid Build Coastguard Worker if len(commands) == 0 { 553*333d2b36SAndroid Build Coastguard Worker return 554*333d2b36SAndroid Build Coastguard Worker } 555*333d2b36SAndroid Build Coastguard Worker if len(outputs) == 0 { 556*333d2b36SAndroid Build Coastguard Worker panic("No outputs specified from any Commands") 557*333d2b36SAndroid Build Coastguard Worker } 558*333d2b36SAndroid Build Coastguard Worker 559*333d2b36SAndroid Build Coastguard Worker commandString := strings.Join(commands, " && ") 560*333d2b36SAndroid Build Coastguard Worker 561*333d2b36SAndroid Build Coastguard Worker if !r.sbox { 562*333d2b36SAndroid Build Coastguard Worker // If not using sbox the rule will run the command directly, put the hash of the 563*333d2b36SAndroid Build Coastguard Worker // list of input files in a comment at the end of the command line to ensure ninja 564*333d2b36SAndroid Build Coastguard Worker // reruns the rule when the list of input files changes. 565*333d2b36SAndroid Build Coastguard Worker commandString += " # hash of input list: " + hashSrcFiles(inputs) 566*333d2b36SAndroid Build Coastguard Worker } 567*333d2b36SAndroid Build Coastguard Worker 568*333d2b36SAndroid Build Coastguard Worker if r.nsjail { 569*333d2b36SAndroid Build Coastguard Worker var nsjailCmd strings.Builder 570*333d2b36SAndroid Build Coastguard Worker nsjailPath := r.ctx.Config().PrebuiltBuildTool(r.ctx, "nsjail") 571*333d2b36SAndroid Build Coastguard Worker if !r.nsjailKeepGendir { 572*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString("rm -rf ") 573*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.nsjailBasePath.String()) 574*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteRune(' ') 575*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.outDir.String()) 576*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" && ") 577*333d2b36SAndroid Build Coastguard Worker } 578*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString("mkdir -p ") 579*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.nsjailBasePath.String()) 580*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteRune(' ') 581*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.outDir.String()) 582*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" && ") 583*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(nsjailPath.String()) 584*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteRune(' ') 585*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString("-B $PWD/") 586*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.nsjailBasePath.String()) 587*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(":nsjail_build_sandbox") 588*333d2b36SAndroid Build Coastguard Worker 589*333d2b36SAndroid Build Coastguard Worker // out is mounted to $(genDir). 590*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -B $PWD/") 591*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(r.outDir.String()) 592*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(":nsjail_build_sandbox/out") 593*333d2b36SAndroid Build Coastguard Worker 594*333d2b36SAndroid Build Coastguard Worker addBindMount := func(src, dst string) { 595*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R $PWD/") 596*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(src) 597*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(":nsjail_build_sandbox/") 598*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(dst) 599*333d2b36SAndroid Build Coastguard Worker } 600*333d2b36SAndroid Build Coastguard Worker 601*333d2b36SAndroid Build Coastguard Worker for _, input := range inputs { 602*333d2b36SAndroid Build Coastguard Worker addBindMount(input.String(), r.nsjailPathForInputRel(input)) 603*333d2b36SAndroid Build Coastguard Worker } 604*333d2b36SAndroid Build Coastguard Worker for _, tool := range tools { 605*333d2b36SAndroid Build Coastguard Worker addBindMount(tool.String(), nsjailPathForToolRel(r.ctx, tool)) 606*333d2b36SAndroid Build Coastguard Worker } 607*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, tools...) 608*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 609*333d2b36SAndroid Build Coastguard Worker for _, directory := range c.implicitDirectories { 610*333d2b36SAndroid Build Coastguard Worker addBindMount(directory.String(), directory.String()) 611*333d2b36SAndroid Build Coastguard Worker // TODO(b/375551969): Add implicitDirectories to BuildParams, rather than relying on implicits 612*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, SourcePath{basePath: directory.base()}) 613*333d2b36SAndroid Build Coastguard Worker } 614*333d2b36SAndroid Build Coastguard Worker for _, tool := range c.packagedTools { 615*333d2b36SAndroid Build Coastguard Worker addBindMount(tool.srcPath.String(), nsjailPathForPackagedToolRel(tool)) 616*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, tool.srcPath) 617*333d2b36SAndroid Build Coastguard Worker } 618*333d2b36SAndroid Build Coastguard Worker } 619*333d2b36SAndroid Build Coastguard Worker 620*333d2b36SAndroid Build Coastguard Worker // These five directories are necessary to run native host tools like /bin/bash and py3-cmd. 621*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R /bin") 622*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R /lib") 623*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R /lib64") 624*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R /dev") 625*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -R /usr") 626*333d2b36SAndroid Build Coastguard Worker 627*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -m none:/tmp:tmpfs:size=1073741824") // 1GB, should be enough 628*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -D nsjail_build_sandbox") 629*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" --disable_rlimits") 630*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" --skip_setsid") // ABFS relies on process-groups to track file operations 631*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -q") 632*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(" -- ") 633*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString("/bin/bash -c ") 634*333d2b36SAndroid Build Coastguard Worker nsjailCmd.WriteString(proptools.ShellEscape(commandString)) 635*333d2b36SAndroid Build Coastguard Worker 636*333d2b36SAndroid Build Coastguard Worker commandString = nsjailCmd.String() 637*333d2b36SAndroid Build Coastguard Worker 638*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, nsjailPath) 639*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, r.nsjailImplicits...) 640*333d2b36SAndroid Build Coastguard Worker } else if r.sbox { 641*333d2b36SAndroid Build Coastguard Worker // If running the command inside sbox, write the rule data out to an sbox 642*333d2b36SAndroid Build Coastguard Worker // manifest.textproto. 643*333d2b36SAndroid Build Coastguard Worker manifest := sbox_proto.Manifest{} 644*333d2b36SAndroid Build Coastguard Worker command := sbox_proto.Command{} 645*333d2b36SAndroid Build Coastguard Worker manifest.Commands = append(manifest.Commands, &command) 646*333d2b36SAndroid Build Coastguard Worker command.Command = proto.String(commandString) 647*333d2b36SAndroid Build Coastguard Worker 648*333d2b36SAndroid Build Coastguard Worker if depFile != nil { 649*333d2b36SAndroid Build Coastguard Worker manifest.OutputDepfile = proto.String(depFile.String()) 650*333d2b36SAndroid Build Coastguard Worker } 651*333d2b36SAndroid Build Coastguard Worker 652*333d2b36SAndroid Build Coastguard Worker // If sandboxing tools is enabled, add copy rules to the manifest to copy each tool 653*333d2b36SAndroid Build Coastguard Worker // into the sbox directory. 654*333d2b36SAndroid Build Coastguard Worker if r.sboxTools { 655*333d2b36SAndroid Build Coastguard Worker for _, tool := range tools { 656*333d2b36SAndroid Build Coastguard Worker command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ 657*333d2b36SAndroid Build Coastguard Worker From: proto.String(tool.String()), 658*333d2b36SAndroid Build Coastguard Worker To: proto.String(sboxPathForToolRel(r.ctx, tool)), 659*333d2b36SAndroid Build Coastguard Worker }) 660*333d2b36SAndroid Build Coastguard Worker } 661*333d2b36SAndroid Build Coastguard Worker for _, c := range r.commands { 662*333d2b36SAndroid Build Coastguard Worker for _, tool := range c.packagedTools { 663*333d2b36SAndroid Build Coastguard Worker command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ 664*333d2b36SAndroid Build Coastguard Worker From: proto.String(tool.srcPath.String()), 665*333d2b36SAndroid Build Coastguard Worker To: proto.String(sboxPathForPackagedToolRel(tool)), 666*333d2b36SAndroid Build Coastguard Worker Executable: proto.Bool(tool.executable), 667*333d2b36SAndroid Build Coastguard Worker }) 668*333d2b36SAndroid Build Coastguard Worker tools = append(tools, tool.srcPath) 669*333d2b36SAndroid Build Coastguard Worker } 670*333d2b36SAndroid Build Coastguard Worker } 671*333d2b36SAndroid Build Coastguard Worker } 672*333d2b36SAndroid Build Coastguard Worker 673*333d2b36SAndroid Build Coastguard Worker // If sandboxing inputs is enabled, add copy rules to the manifest to copy each input 674*333d2b36SAndroid Build Coastguard Worker // into the sbox directory. 675*333d2b36SAndroid Build Coastguard Worker if r.sboxInputs { 676*333d2b36SAndroid Build Coastguard Worker for _, input := range inputs { 677*333d2b36SAndroid Build Coastguard Worker command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ 678*333d2b36SAndroid Build Coastguard Worker From: proto.String(input.String()), 679*333d2b36SAndroid Build Coastguard Worker To: proto.String(r.sboxPathForInputRel(input)), 680*333d2b36SAndroid Build Coastguard Worker }) 681*333d2b36SAndroid Build Coastguard Worker } 682*333d2b36SAndroid Build Coastguard Worker for _, input := range r.OrderOnlys() { 683*333d2b36SAndroid Build Coastguard Worker command.CopyBefore = append(command.CopyBefore, &sbox_proto.Copy{ 684*333d2b36SAndroid Build Coastguard Worker From: proto.String(input.String()), 685*333d2b36SAndroid Build Coastguard Worker To: proto.String(r.sboxPathForInputRel(input)), 686*333d2b36SAndroid Build Coastguard Worker }) 687*333d2b36SAndroid Build Coastguard Worker } 688*333d2b36SAndroid Build Coastguard Worker 689*333d2b36SAndroid Build Coastguard Worker // If using rsp files copy them and their contents into the sbox directory with 690*333d2b36SAndroid Build Coastguard Worker // the appropriate path mappings. 691*333d2b36SAndroid Build Coastguard Worker for _, rspFile := range rspFiles { 692*333d2b36SAndroid Build Coastguard Worker command.RspFiles = append(command.RspFiles, &sbox_proto.RspFile{ 693*333d2b36SAndroid Build Coastguard Worker File: proto.String(rspFile.file.String()), 694*333d2b36SAndroid Build Coastguard Worker // These have to match the logic in sboxPathForInputRel 695*333d2b36SAndroid Build Coastguard Worker PathMappings: []*sbox_proto.PathMapping{ 696*333d2b36SAndroid Build Coastguard Worker { 697*333d2b36SAndroid Build Coastguard Worker From: proto.String(r.outDir.String()), 698*333d2b36SAndroid Build Coastguard Worker To: proto.String(sboxOutSubDir), 699*333d2b36SAndroid Build Coastguard Worker }, 700*333d2b36SAndroid Build Coastguard Worker { 701*333d2b36SAndroid Build Coastguard Worker From: proto.String(r.ctx.Config().OutDir()), 702*333d2b36SAndroid Build Coastguard Worker To: proto.String(sboxOutSubDir), 703*333d2b36SAndroid Build Coastguard Worker }, 704*333d2b36SAndroid Build Coastguard Worker }, 705*333d2b36SAndroid Build Coastguard Worker }) 706*333d2b36SAndroid Build Coastguard Worker } 707*333d2b36SAndroid Build Coastguard Worker 708*333d2b36SAndroid Build Coastguard Worker // Only allow the build to access certain environment variables 709*333d2b36SAndroid Build Coastguard Worker command.DontInheritEnv = proto.Bool(true) 710*333d2b36SAndroid Build Coastguard Worker command.Env = r.ctx.Config().Once(sandboxEnvOnceKey, func() interface{} { 711*333d2b36SAndroid Build Coastguard Worker // The list of allowed variables was found by running builds of all 712*333d2b36SAndroid Build Coastguard Worker // genrules and seeing what failed 713*333d2b36SAndroid Build Coastguard Worker var result []*sbox_proto.EnvironmentVariable 714*333d2b36SAndroid Build Coastguard Worker inheritedVars := []string{ 715*333d2b36SAndroid Build Coastguard Worker "PATH", 716*333d2b36SAndroid Build Coastguard Worker "JAVA_HOME", 717*333d2b36SAndroid Build Coastguard Worker "TMPDIR", 718*333d2b36SAndroid Build Coastguard Worker // Allow RBE variables because the art tests invoke RBE manually 719*333d2b36SAndroid Build Coastguard Worker "RBE_log_dir", 720*333d2b36SAndroid Build Coastguard Worker "RBE_platform", 721*333d2b36SAndroid Build Coastguard Worker "RBE_server_address", 722*333d2b36SAndroid Build Coastguard Worker // TODO: RBE_exec_root is set to the absolute path to the root of the source 723*333d2b36SAndroid Build Coastguard Worker // tree, which we don't want sandboxed actions to find. Remap it to ".". 724*333d2b36SAndroid Build Coastguard Worker "RBE_exec_root", 725*333d2b36SAndroid Build Coastguard Worker } 726*333d2b36SAndroid Build Coastguard Worker for _, v := range inheritedVars { 727*333d2b36SAndroid Build Coastguard Worker result = append(result, &sbox_proto.EnvironmentVariable{ 728*333d2b36SAndroid Build Coastguard Worker Name: proto.String(v), 729*333d2b36SAndroid Build Coastguard Worker State: &sbox_proto.EnvironmentVariable_Inherit{ 730*333d2b36SAndroid Build Coastguard Worker Inherit: true, 731*333d2b36SAndroid Build Coastguard Worker }, 732*333d2b36SAndroid Build Coastguard Worker }) 733*333d2b36SAndroid Build Coastguard Worker } 734*333d2b36SAndroid Build Coastguard Worker // Set OUT_DIR to the relative path of the sandboxed out directory. 735*333d2b36SAndroid Build Coastguard Worker // Otherwise, OUT_DIR will be inherited from the rest of the build, 736*333d2b36SAndroid Build Coastguard Worker // which will allow scripts to escape the sandbox if OUT_DIR is an 737*333d2b36SAndroid Build Coastguard Worker // absolute path. 738*333d2b36SAndroid Build Coastguard Worker result = append(result, &sbox_proto.EnvironmentVariable{ 739*333d2b36SAndroid Build Coastguard Worker Name: proto.String("OUT_DIR"), 740*333d2b36SAndroid Build Coastguard Worker State: &sbox_proto.EnvironmentVariable_Value{ 741*333d2b36SAndroid Build Coastguard Worker Value: sboxOutSubDir, 742*333d2b36SAndroid Build Coastguard Worker }, 743*333d2b36SAndroid Build Coastguard Worker }) 744*333d2b36SAndroid Build Coastguard Worker return result 745*333d2b36SAndroid Build Coastguard Worker }).([]*sbox_proto.EnvironmentVariable) 746*333d2b36SAndroid Build Coastguard Worker command.Chdir = proto.Bool(true) 747*333d2b36SAndroid Build Coastguard Worker } 748*333d2b36SAndroid Build Coastguard Worker 749*333d2b36SAndroid Build Coastguard Worker // Add copy rules to the manifest to copy each output file from the sbox directory. 750*333d2b36SAndroid Build Coastguard Worker // to the output directory after running the commands. 751*333d2b36SAndroid Build Coastguard Worker for _, output := range outputs { 752*333d2b36SAndroid Build Coastguard Worker rel := Rel(r.ctx, r.outDir.String(), output.String()) 753*333d2b36SAndroid Build Coastguard Worker command.CopyAfter = append(command.CopyAfter, &sbox_proto.Copy{ 754*333d2b36SAndroid Build Coastguard Worker From: proto.String(filepath.Join(r.sboxOutSubDir, rel)), 755*333d2b36SAndroid Build Coastguard Worker To: proto.String(output.String()), 756*333d2b36SAndroid Build Coastguard Worker }) 757*333d2b36SAndroid Build Coastguard Worker } 758*333d2b36SAndroid Build Coastguard Worker 759*333d2b36SAndroid Build Coastguard Worker // Outputs that were marked Temporary will not be checked that they are in the output 760*333d2b36SAndroid Build Coastguard Worker // directory by the loop above, check them here. 761*333d2b36SAndroid Build Coastguard Worker for path := range r.temporariesSet { 762*333d2b36SAndroid Build Coastguard Worker Rel(r.ctx, r.outDir.String(), path.String()) 763*333d2b36SAndroid Build Coastguard Worker } 764*333d2b36SAndroid Build Coastguard Worker 765*333d2b36SAndroid Build Coastguard Worker // Add a hash of the list of input files to the manifest so that the textproto file 766*333d2b36SAndroid Build Coastguard Worker // changes when the list of input files changes and causes the sbox rule that 767*333d2b36SAndroid Build Coastguard Worker // depends on it to rerun. 768*333d2b36SAndroid Build Coastguard Worker command.InputHash = proto.String(hashSrcFiles(inputs)) 769*333d2b36SAndroid Build Coastguard Worker 770*333d2b36SAndroid Build Coastguard Worker // Verify that the manifest textproto is not inside the sbox output directory, otherwise 771*333d2b36SAndroid Build Coastguard Worker // it will get deleted when the sbox rule clears its output directory. 772*333d2b36SAndroid Build Coastguard Worker _, manifestInOutDir := MaybeRel(r.ctx, r.outDir.String(), r.sboxManifestPath.String()) 773*333d2b36SAndroid Build Coastguard Worker if manifestInOutDir { 774*333d2b36SAndroid Build Coastguard Worker ReportPathErrorf(r.ctx, "sbox rule %q manifestPath %q must not be in outputDir %q", 775*333d2b36SAndroid Build Coastguard Worker name, r.sboxManifestPath.String(), r.outDir.String()) 776*333d2b36SAndroid Build Coastguard Worker } 777*333d2b36SAndroid Build Coastguard Worker 778*333d2b36SAndroid Build Coastguard Worker // Create a rule to write the manifest as textproto. Pretty print it by indenting and 779*333d2b36SAndroid Build Coastguard Worker // splitting across multiple lines. 780*333d2b36SAndroid Build Coastguard Worker pbText, err := prototext.MarshalOptions{Indent: " "}.Marshal(&manifest) 781*333d2b36SAndroid Build Coastguard Worker if err != nil { 782*333d2b36SAndroid Build Coastguard Worker ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err) 783*333d2b36SAndroid Build Coastguard Worker } 784*333d2b36SAndroid Build Coastguard Worker WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText)) 785*333d2b36SAndroid Build Coastguard Worker 786*333d2b36SAndroid Build Coastguard Worker // Generate a new string to use as the command line of the sbox rule. This uses 787*333d2b36SAndroid Build Coastguard Worker // a RuleBuilderCommand as a convenience method of building the command line, then 788*333d2b36SAndroid Build Coastguard Worker // converts it to a string to replace commandString. 789*333d2b36SAndroid Build Coastguard Worker sboxCmd := &RuleBuilderCommand{ 790*333d2b36SAndroid Build Coastguard Worker rule: &RuleBuilder{ 791*333d2b36SAndroid Build Coastguard Worker ctx: r.ctx, 792*333d2b36SAndroid Build Coastguard Worker }, 793*333d2b36SAndroid Build Coastguard Worker } 794*333d2b36SAndroid Build Coastguard Worker sboxCmd.builtToolWithoutDeps("sbox"). 795*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--sandbox-path ", shared.TempDirForOutDir(PathForOutput(r.ctx).String())). 796*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--output-dir ", r.outDir.String()). 797*333d2b36SAndroid Build Coastguard Worker FlagWithInput("--manifest ", r.sboxManifestPath) 798*333d2b36SAndroid Build Coastguard Worker 799*333d2b36SAndroid Build Coastguard Worker if r.restat { 800*333d2b36SAndroid Build Coastguard Worker sboxCmd.Flag("--write-if-changed") 801*333d2b36SAndroid Build Coastguard Worker } 802*333d2b36SAndroid Build Coastguard Worker 803*333d2b36SAndroid Build Coastguard Worker // Replace the command string, and add the sbox tool and manifest textproto to the 804*333d2b36SAndroid Build Coastguard Worker // dependencies of the final sbox rule. 805*333d2b36SAndroid Build Coastguard Worker commandString = sboxCmd.buf.String() 806*333d2b36SAndroid Build Coastguard Worker tools = append(tools, sboxCmd.tools...) 807*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, sboxCmd.inputs...) 808*333d2b36SAndroid Build Coastguard Worker 809*333d2b36SAndroid Build Coastguard Worker if r.rbeParams != nil { 810*333d2b36SAndroid Build Coastguard Worker // RBE needs a list of input files to copy to the remote builder. For inputs already 811*333d2b36SAndroid Build Coastguard Worker // listed in an rsp file, pass the rsp file directly to rewrapper. For the rest, 812*333d2b36SAndroid Build Coastguard Worker // create a new rsp file to pass to rewrapper. 813*333d2b36SAndroid Build Coastguard Worker var remoteRspFiles Paths 814*333d2b36SAndroid Build Coastguard Worker var remoteInputs Paths 815*333d2b36SAndroid Build Coastguard Worker 816*333d2b36SAndroid Build Coastguard Worker remoteInputs = append(remoteInputs, inputs...) 817*333d2b36SAndroid Build Coastguard Worker remoteInputs = append(remoteInputs, tools...) 818*333d2b36SAndroid Build Coastguard Worker 819*333d2b36SAndroid Build Coastguard Worker for _, rspFile := range rspFiles { 820*333d2b36SAndroid Build Coastguard Worker remoteInputs = append(remoteInputs, rspFile.file) 821*333d2b36SAndroid Build Coastguard Worker remoteRspFiles = append(remoteRspFiles, rspFile.file) 822*333d2b36SAndroid Build Coastguard Worker } 823*333d2b36SAndroid Build Coastguard Worker 824*333d2b36SAndroid Build Coastguard Worker if len(remoteInputs) > 0 { 825*333d2b36SAndroid Build Coastguard Worker inputsListFile := r.sboxManifestPath.ReplaceExtension(r.ctx, "rbe_inputs.list") 826*333d2b36SAndroid Build Coastguard Worker writeRspFileRule(r.ctx, inputsListFile, remoteInputs) 827*333d2b36SAndroid Build Coastguard Worker remoteRspFiles = append(remoteRspFiles, inputsListFile) 828*333d2b36SAndroid Build Coastguard Worker // Add the new rsp file as an extra input to the rule. 829*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, inputsListFile) 830*333d2b36SAndroid Build Coastguard Worker } 831*333d2b36SAndroid Build Coastguard Worker 832*333d2b36SAndroid Build Coastguard Worker r.rbeParams.OutputFiles = outputs.Strings() 833*333d2b36SAndroid Build Coastguard Worker r.rbeParams.RSPFiles = remoteRspFiles.Strings() 834*333d2b36SAndroid Build Coastguard Worker rewrapperCommand := r.rbeParams.NoVarTemplate(r.ctx.Config().RBEWrapper()) 835*333d2b36SAndroid Build Coastguard Worker commandString = rewrapperCommand + " bash -c '" + strings.ReplaceAll(commandString, `'`, `'\''`) + "'" 836*333d2b36SAndroid Build Coastguard Worker } 837*333d2b36SAndroid Build Coastguard Worker } 838*333d2b36SAndroid Build Coastguard Worker 839*333d2b36SAndroid Build Coastguard Worker // Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to 840*333d2b36SAndroid Build Coastguard Worker // ImplicitOutputs. RuleBuilder doesn't use "$out", so the distinction between Outputs and 841*333d2b36SAndroid Build Coastguard Worker // ImplicitOutputs doesn't matter. 842*333d2b36SAndroid Build Coastguard Worker output := outputs[0] 843*333d2b36SAndroid Build Coastguard Worker implicitOutputs := outputs[1:] 844*333d2b36SAndroid Build Coastguard Worker 845*333d2b36SAndroid Build Coastguard Worker var rspFile, rspFileContent string 846*333d2b36SAndroid Build Coastguard Worker var rspFileInputs Paths 847*333d2b36SAndroid Build Coastguard Worker if len(rspFiles) > 0 { 848*333d2b36SAndroid Build Coastguard Worker // The first rsp files uses Ninja's rsp file support for the rule 849*333d2b36SAndroid Build Coastguard Worker rspFile = rspFiles[0].file.String() 850*333d2b36SAndroid Build Coastguard Worker // Use "$in" for rspFileContent to avoid duplicating the list of files in the dependency 851*333d2b36SAndroid Build Coastguard Worker // list and in the contents of the rsp file. Inputs to the rule that are not in the 852*333d2b36SAndroid Build Coastguard Worker // rsp file will be listed in Implicits instead of Inputs so they don't show up in "$in". 853*333d2b36SAndroid Build Coastguard Worker rspFileContent = "$in" 854*333d2b36SAndroid Build Coastguard Worker rspFileInputs = append(rspFileInputs, rspFiles[0].paths...) 855*333d2b36SAndroid Build Coastguard Worker 856*333d2b36SAndroid Build Coastguard Worker for _, rspFile := range rspFiles[1:] { 857*333d2b36SAndroid Build Coastguard Worker // Any additional rsp files need an extra rule to write the file. 858*333d2b36SAndroid Build Coastguard Worker writeRspFileRule(r.ctx, rspFile.file, rspFile.paths) 859*333d2b36SAndroid Build Coastguard Worker // The main rule needs to depend on the inputs listed in the extra rsp file. 860*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, rspFile.paths...) 861*333d2b36SAndroid Build Coastguard Worker // The main rule needs to depend on the extra rsp file. 862*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, rspFile.file) 863*333d2b36SAndroid Build Coastguard Worker } 864*333d2b36SAndroid Build Coastguard Worker } 865*333d2b36SAndroid Build Coastguard Worker 866*333d2b36SAndroid Build Coastguard Worker var pool blueprint.Pool 867*333d2b36SAndroid Build Coastguard Worker if r.ctx.Config().UseGoma() && r.remoteable.Goma { 868*333d2b36SAndroid Build Coastguard Worker // When USE_GOMA=true is set and the rule is supported by goma, allow jobs to run outside the local pool. 869*333d2b36SAndroid Build Coastguard Worker } else if r.ctx.Config().UseRBE() && r.remoteable.RBE { 870*333d2b36SAndroid Build Coastguard Worker // When USE_RBE=true is set and the rule is supported by RBE, use the remotePool. 871*333d2b36SAndroid Build Coastguard Worker pool = remotePool 872*333d2b36SAndroid Build Coastguard Worker } else if r.highmem { 873*333d2b36SAndroid Build Coastguard Worker pool = highmemPool 874*333d2b36SAndroid Build Coastguard Worker } else if r.ctx.Config().UseRemoteBuild() { 875*333d2b36SAndroid Build Coastguard Worker pool = localPool 876*333d2b36SAndroid Build Coastguard Worker } 877*333d2b36SAndroid Build Coastguard Worker 878*333d2b36SAndroid Build Coastguard Worker // If the command length is getting close to linux's maximum, dump it to a file, which allows 879*333d2b36SAndroid Build Coastguard Worker // for longer commands. 880*333d2b36SAndroid Build Coastguard Worker if len(commandString) > 100000 { 881*333d2b36SAndroid Build Coastguard Worker hasher := sha256.New() 882*333d2b36SAndroid Build Coastguard Worker hasher.Write([]byte(output.String())) 883*333d2b36SAndroid Build Coastguard Worker script := PathForOutput(r.ctx, "rule_builder_scripts", fmt.Sprintf("%x.sh", hasher.Sum(nil))) 884*333d2b36SAndroid Build Coastguard Worker commandString = "set -eu\n\n" + commandString + "\n" 885*333d2b36SAndroid Build Coastguard Worker WriteExecutableFileRuleVerbatim(r.ctx, script, commandString) 886*333d2b36SAndroid Build Coastguard Worker inputs = append(inputs, script) 887*333d2b36SAndroid Build Coastguard Worker commandString = script.String() 888*333d2b36SAndroid Build Coastguard Worker } 889*333d2b36SAndroid Build Coastguard Worker 890*333d2b36SAndroid Build Coastguard Worker commandString = proptools.NinjaEscape(commandString) 891*333d2b36SAndroid Build Coastguard Worker 892*333d2b36SAndroid Build Coastguard Worker args_vars := make([]string, len(r.args)) 893*333d2b36SAndroid Build Coastguard Worker i := 0 894*333d2b36SAndroid Build Coastguard Worker for k, _ := range r.args { 895*333d2b36SAndroid Build Coastguard Worker args_vars[i] = k 896*333d2b36SAndroid Build Coastguard Worker i++ 897*333d2b36SAndroid Build Coastguard Worker } 898*333d2b36SAndroid Build Coastguard Worker r.ctx.Build(r.pctx, BuildParams{ 899*333d2b36SAndroid Build Coastguard Worker Rule: r.ctx.Rule(r.pctx, name, blueprint.RuleParams{ 900*333d2b36SAndroid Build Coastguard Worker Command: commandString, 901*333d2b36SAndroid Build Coastguard Worker CommandDeps: proptools.NinjaEscapeList(tools.Strings()), 902*333d2b36SAndroid Build Coastguard Worker Restat: r.restat, 903*333d2b36SAndroid Build Coastguard Worker Rspfile: proptools.NinjaEscape(rspFile), 904*333d2b36SAndroid Build Coastguard Worker RspfileContent: rspFileContent, 905*333d2b36SAndroid Build Coastguard Worker Pool: pool, 906*333d2b36SAndroid Build Coastguard Worker }, args_vars...), 907*333d2b36SAndroid Build Coastguard Worker Inputs: rspFileInputs, 908*333d2b36SAndroid Build Coastguard Worker Implicits: inputs, 909*333d2b36SAndroid Build Coastguard Worker OrderOnly: r.OrderOnlys(), 910*333d2b36SAndroid Build Coastguard Worker Validations: r.Validations(), 911*333d2b36SAndroid Build Coastguard Worker Output: output, 912*333d2b36SAndroid Build Coastguard Worker ImplicitOutputs: implicitOutputs, 913*333d2b36SAndroid Build Coastguard Worker Depfile: depFile, 914*333d2b36SAndroid Build Coastguard Worker Deps: depFormat, 915*333d2b36SAndroid Build Coastguard Worker Description: desc, 916*333d2b36SAndroid Build Coastguard Worker Args: r.args, 917*333d2b36SAndroid Build Coastguard Worker }) 918*333d2b36SAndroid Build Coastguard Worker} 919*333d2b36SAndroid Build Coastguard Worker 920*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand is a builder for a command in a command line. It can be mutated by its methods to add to the 921*333d2b36SAndroid Build Coastguard Worker// command and track dependencies. The methods mutate the RuleBuilderCommand in place, as well as return the 922*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single 923*333d2b36SAndroid Build Coastguard Worker// space as a separator from the previous method. 924*333d2b36SAndroid Build Coastguard Workertype RuleBuilderCommand struct { 925*333d2b36SAndroid Build Coastguard Worker rule *RuleBuilder 926*333d2b36SAndroid Build Coastguard Worker 927*333d2b36SAndroid Build Coastguard Worker buf strings.Builder 928*333d2b36SAndroid Build Coastguard Worker inputs Paths 929*333d2b36SAndroid Build Coastguard Worker implicits Paths 930*333d2b36SAndroid Build Coastguard Worker orderOnlys Paths 931*333d2b36SAndroid Build Coastguard Worker validations Paths 932*333d2b36SAndroid Build Coastguard Worker outputs WritablePaths 933*333d2b36SAndroid Build Coastguard Worker depFiles WritablePaths 934*333d2b36SAndroid Build Coastguard Worker tools Paths 935*333d2b36SAndroid Build Coastguard Worker packagedTools []PackagingSpec 936*333d2b36SAndroid Build Coastguard Worker rspFiles []rspFileAndPaths 937*333d2b36SAndroid Build Coastguard Worker implicitDirectories DirectoryPaths 938*333d2b36SAndroid Build Coastguard Worker} 939*333d2b36SAndroid Build Coastguard Worker 940*333d2b36SAndroid Build Coastguard Workertype rspFileAndPaths struct { 941*333d2b36SAndroid Build Coastguard Worker file WritablePath 942*333d2b36SAndroid Build Coastguard Worker paths Paths 943*333d2b36SAndroid Build Coastguard Worker} 944*333d2b36SAndroid Build Coastguard Worker 945*333d2b36SAndroid Build Coastguard Workerfunc checkPathNotNil(path Path) { 946*333d2b36SAndroid Build Coastguard Worker if path == nil { 947*333d2b36SAndroid Build Coastguard Worker panic("rule_builder paths cannot be nil") 948*333d2b36SAndroid Build Coastguard Worker } 949*333d2b36SAndroid Build Coastguard Worker} 950*333d2b36SAndroid Build Coastguard Worker 951*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) addInput(path Path) string { 952*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 953*333d2b36SAndroid Build Coastguard Worker c.inputs = append(c.inputs, path) 954*333d2b36SAndroid Build Coastguard Worker return c.PathForInput(path) 955*333d2b36SAndroid Build Coastguard Worker} 956*333d2b36SAndroid Build Coastguard Worker 957*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) addImplicit(path Path) { 958*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 959*333d2b36SAndroid Build Coastguard Worker c.implicits = append(c.implicits, path) 960*333d2b36SAndroid Build Coastguard Worker} 961*333d2b36SAndroid Build Coastguard Worker 962*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) addImplicitDirectory(path DirectoryPath) { 963*333d2b36SAndroid Build Coastguard Worker c.implicitDirectories = append(c.implicitDirectories, path) 964*333d2b36SAndroid Build Coastguard Worker} 965*333d2b36SAndroid Build Coastguard Worker 966*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) addOrderOnly(path Path) { 967*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 968*333d2b36SAndroid Build Coastguard Worker c.orderOnlys = append(c.orderOnlys, path) 969*333d2b36SAndroid Build Coastguard Worker} 970*333d2b36SAndroid Build Coastguard Worker 971*333d2b36SAndroid Build Coastguard Worker// PathForInput takes an input path and returns the appropriate path to use on the command line. If 972*333d2b36SAndroid Build Coastguard Worker// sbox was enabled via a call to RuleBuilder.Sbox() and the path was an output path it returns a 973*333d2b36SAndroid Build Coastguard Worker// path with the placeholder prefix used for outputs in sbox. If sbox is not enabled it returns the 974*333d2b36SAndroid Build Coastguard Worker// original path. 975*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathForInput(path Path) string { 976*333d2b36SAndroid Build Coastguard Worker if c.rule.sbox { 977*333d2b36SAndroid Build Coastguard Worker rel, inSandbox := c.rule._sboxPathForInputRel(path) 978*333d2b36SAndroid Build Coastguard Worker if inSandbox { 979*333d2b36SAndroid Build Coastguard Worker rel = filepath.Join(sboxSandboxBaseDir, rel) 980*333d2b36SAndroid Build Coastguard Worker } 981*333d2b36SAndroid Build Coastguard Worker return rel 982*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 983*333d2b36SAndroid Build Coastguard Worker return c.rule.nsjailPathForInputRel(path) 984*333d2b36SAndroid Build Coastguard Worker } 985*333d2b36SAndroid Build Coastguard Worker return path.String() 986*333d2b36SAndroid Build Coastguard Worker} 987*333d2b36SAndroid Build Coastguard Worker 988*333d2b36SAndroid Build Coastguard Worker// PathsForInputs takes a list of input paths and returns the appropriate paths to use on the 989*333d2b36SAndroid Build Coastguard Worker// command line. If sbox was enabled via a call to RuleBuilder.Sbox() a path was an output path, it 990*333d2b36SAndroid Build Coastguard Worker// returns the path with the placeholder prefix used for outputs in sbox. If sbox is not enabled it 991*333d2b36SAndroid Build Coastguard Worker// returns the original paths. 992*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathsForInputs(paths Paths) []string { 993*333d2b36SAndroid Build Coastguard Worker ret := make([]string, len(paths)) 994*333d2b36SAndroid Build Coastguard Worker for i, path := range paths { 995*333d2b36SAndroid Build Coastguard Worker ret[i] = c.PathForInput(path) 996*333d2b36SAndroid Build Coastguard Worker } 997*333d2b36SAndroid Build Coastguard Worker return ret 998*333d2b36SAndroid Build Coastguard Worker} 999*333d2b36SAndroid Build Coastguard Worker 1000*333d2b36SAndroid Build Coastguard Worker// PathForOutput takes an output path and returns the appropriate path to use on the command 1001*333d2b36SAndroid Build Coastguard Worker// line. If sbox was enabled via a call to RuleBuilder.Sbox(), it returns a path with the 1002*333d2b36SAndroid Build Coastguard Worker// placeholder prefix used for outputs in sbox. If sbox is not enabled it returns the 1003*333d2b36SAndroid Build Coastguard Worker// original path. 1004*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathForOutput(path WritablePath) string { 1005*333d2b36SAndroid Build Coastguard Worker if c.rule.sbox { 1006*333d2b36SAndroid Build Coastguard Worker // Errors will be handled in RuleBuilder.Build where we have a context to report them 1007*333d2b36SAndroid Build Coastguard Worker rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String()) 1008*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxOutDir, rel) 1009*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 1010*333d2b36SAndroid Build Coastguard Worker // Errors will be handled in RuleBuilder.Build where we have a context to report them 1011*333d2b36SAndroid Build Coastguard Worker rel, _, _ := maybeRelErr(c.rule.outDir.String(), path.String()) 1012*333d2b36SAndroid Build Coastguard Worker return filepath.Join(nsjailOutDir, rel) 1013*333d2b36SAndroid Build Coastguard Worker } 1014*333d2b36SAndroid Build Coastguard Worker return path.String() 1015*333d2b36SAndroid Build Coastguard Worker} 1016*333d2b36SAndroid Build Coastguard Worker 1017*333d2b36SAndroid Build Coastguard Workerfunc sboxPathForToolRel(ctx BuilderContext, path Path) string { 1018*333d2b36SAndroid Build Coastguard Worker // Errors will be handled in RuleBuilder.Build where we have a context to report them 1019*333d2b36SAndroid Build Coastguard Worker toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "") 1020*333d2b36SAndroid Build Coastguard Worker relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String()) 1021*333d2b36SAndroid Build Coastguard Worker if isRelOutSoong { 1022*333d2b36SAndroid Build Coastguard Worker // The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out 1023*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxToolsSubDir, "out", relOutSoong) 1024*333d2b36SAndroid Build Coastguard Worker } 1025*333d2b36SAndroid Build Coastguard Worker // The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src 1026*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxToolsSubDir, "src", path.String()) 1027*333d2b36SAndroid Build Coastguard Worker} 1028*333d2b36SAndroid Build Coastguard Worker 1029*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) _sboxPathForInputRel(path Path) (rel string, inSandbox bool) { 1030*333d2b36SAndroid Build Coastguard Worker // Errors will be handled in RuleBuilder.Build where we have a context to report them 1031*333d2b36SAndroid Build Coastguard Worker rel, isRelSboxOut, _ := maybeRelErr(r.outDir.String(), path.String()) 1032*333d2b36SAndroid Build Coastguard Worker if isRelSboxOut { 1033*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxOutSubDir, rel), true 1034*333d2b36SAndroid Build Coastguard Worker } 1035*333d2b36SAndroid Build Coastguard Worker if r.sboxInputs { 1036*333d2b36SAndroid Build Coastguard Worker // When sandboxing inputs all inputs have to be copied into the sandbox. Input files that 1037*333d2b36SAndroid Build Coastguard Worker // are outputs of other rules could be an arbitrary absolute path if OUT_DIR is set, so they 1038*333d2b36SAndroid Build Coastguard Worker // will be copied to relative paths under __SBOX_OUT_DIR__/out. 1039*333d2b36SAndroid Build Coastguard Worker rel, isRelOut, _ := maybeRelErr(r.ctx.Config().OutDir(), path.String()) 1040*333d2b36SAndroid Build Coastguard Worker if isRelOut { 1041*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxOutSubDir, rel), true 1042*333d2b36SAndroid Build Coastguard Worker } 1043*333d2b36SAndroid Build Coastguard Worker } 1044*333d2b36SAndroid Build Coastguard Worker return path.String(), false 1045*333d2b36SAndroid Build Coastguard Worker} 1046*333d2b36SAndroid Build Coastguard Worker 1047*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) sboxPathForInputRel(path Path) string { 1048*333d2b36SAndroid Build Coastguard Worker rel, _ := r._sboxPathForInputRel(path) 1049*333d2b36SAndroid Build Coastguard Worker return rel 1050*333d2b36SAndroid Build Coastguard Worker} 1051*333d2b36SAndroid Build Coastguard Worker 1052*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) sboxPathsForInputsRel(paths Paths) []string { 1053*333d2b36SAndroid Build Coastguard Worker ret := make([]string, len(paths)) 1054*333d2b36SAndroid Build Coastguard Worker for i, path := range paths { 1055*333d2b36SAndroid Build Coastguard Worker ret[i] = r.sboxPathForInputRel(path) 1056*333d2b36SAndroid Build Coastguard Worker } 1057*333d2b36SAndroid Build Coastguard Worker return ret 1058*333d2b36SAndroid Build Coastguard Worker} 1059*333d2b36SAndroid Build Coastguard Worker 1060*333d2b36SAndroid Build Coastguard Workerfunc sboxPathForPackagedToolRel(spec PackagingSpec) string { 1061*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxToolsSubDir, "out", spec.relPathInPackage) 1062*333d2b36SAndroid Build Coastguard Worker} 1063*333d2b36SAndroid Build Coastguard Worker 1064*333d2b36SAndroid Build Coastguard Workerfunc nsjailPathForToolRel(ctx BuilderContext, path Path) string { 1065*333d2b36SAndroid Build Coastguard Worker // Errors will be handled in RuleBuilder.Build where we have a context to report them 1066*333d2b36SAndroid Build Coastguard Worker toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "") 1067*333d2b36SAndroid Build Coastguard Worker relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String()) 1068*333d2b36SAndroid Build Coastguard Worker if isRelOutSoong { 1069*333d2b36SAndroid Build Coastguard Worker // The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out 1070*333d2b36SAndroid Build Coastguard Worker return filepath.Join(nsjailToolsSubDir, "out", relOutSoong) 1071*333d2b36SAndroid Build Coastguard Worker } 1072*333d2b36SAndroid Build Coastguard Worker // The tool is in the source directory, it will be copied to __SBOX_OUT_DIR__/tools/src 1073*333d2b36SAndroid Build Coastguard Worker return filepath.Join(nsjailToolsSubDir, "src", path.String()) 1074*333d2b36SAndroid Build Coastguard Worker} 1075*333d2b36SAndroid Build Coastguard Worker 1076*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) nsjailPathForInputRel(path Path) string { 1077*333d2b36SAndroid Build Coastguard Worker rel, isRelSboxOut, _ := maybeRelErr(r.outDir.String(), path.String()) 1078*333d2b36SAndroid Build Coastguard Worker if isRelSboxOut { 1079*333d2b36SAndroid Build Coastguard Worker return filepath.Join(nsjailOutDir, rel) 1080*333d2b36SAndroid Build Coastguard Worker } 1081*333d2b36SAndroid Build Coastguard Worker return path.String() 1082*333d2b36SAndroid Build Coastguard Worker} 1083*333d2b36SAndroid Build Coastguard Worker 1084*333d2b36SAndroid Build Coastguard Workerfunc (r *RuleBuilder) nsjailPathsForInputsRel(paths Paths) []string { 1085*333d2b36SAndroid Build Coastguard Worker ret := make([]string, len(paths)) 1086*333d2b36SAndroid Build Coastguard Worker for i, path := range paths { 1087*333d2b36SAndroid Build Coastguard Worker ret[i] = r.nsjailPathForInputRel(path) 1088*333d2b36SAndroid Build Coastguard Worker } 1089*333d2b36SAndroid Build Coastguard Worker return ret 1090*333d2b36SAndroid Build Coastguard Worker} 1091*333d2b36SAndroid Build Coastguard Worker 1092*333d2b36SAndroid Build Coastguard Workerfunc nsjailPathForPackagedToolRel(spec PackagingSpec) string { 1093*333d2b36SAndroid Build Coastguard Worker return filepath.Join(nsjailToolsSubDir, "out", spec.relPathInPackage) 1094*333d2b36SAndroid Build Coastguard Worker} 1095*333d2b36SAndroid Build Coastguard Worker 1096*333d2b36SAndroid Build Coastguard Worker// PathForPackagedTool takes a PackageSpec for a tool and returns the corresponding path for the 1097*333d2b36SAndroid Build Coastguard Worker// tool after copying it into the sandbox. This can be used on the RuleBuilder command line to 1098*333d2b36SAndroid Build Coastguard Worker// reference the tool. 1099*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathForPackagedTool(spec PackagingSpec) string { 1100*333d2b36SAndroid Build Coastguard Worker if c.rule.sboxTools { 1101*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxSandboxBaseDir, sboxPathForPackagedToolRel(spec)) 1102*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 1103*333d2b36SAndroid Build Coastguard Worker return nsjailPathForPackagedToolRel(spec) 1104*333d2b36SAndroid Build Coastguard Worker } else { 1105*333d2b36SAndroid Build Coastguard Worker panic("PathForPackagedTool() requires SandboxTools() or Nsjail()") 1106*333d2b36SAndroid Build Coastguard Worker } 1107*333d2b36SAndroid Build Coastguard Worker} 1108*333d2b36SAndroid Build Coastguard Worker 1109*333d2b36SAndroid Build Coastguard Worker// PathForTool takes a path to a tool, which may be an output file or a source file, and returns 1110*333d2b36SAndroid Build Coastguard Worker// the corresponding path for the tool in the sbox sandbox if sbox is enabled, or the original path 1111*333d2b36SAndroid Build Coastguard Worker// if it is not. This can be used on the RuleBuilder command line to reference the tool. 1112*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathForTool(path Path) string { 1113*333d2b36SAndroid Build Coastguard Worker if c.rule.sbox && c.rule.sboxTools { 1114*333d2b36SAndroid Build Coastguard Worker return filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path)) 1115*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 1116*333d2b36SAndroid Build Coastguard Worker return nsjailPathForToolRel(c.rule.ctx, path) 1117*333d2b36SAndroid Build Coastguard Worker } 1118*333d2b36SAndroid Build Coastguard Worker return path.String() 1119*333d2b36SAndroid Build Coastguard Worker} 1120*333d2b36SAndroid Build Coastguard Worker 1121*333d2b36SAndroid Build Coastguard Worker// PathsForTools takes a list of paths to tools, which may be output files or source files, and 1122*333d2b36SAndroid Build Coastguard Worker// returns the corresponding paths for the tools in the sbox sandbox if sbox is enabled, or the 1123*333d2b36SAndroid Build Coastguard Worker// original paths if it is not. This can be used on the RuleBuilder command line to reference the tool. 1124*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PathsForTools(paths Paths) []string { 1125*333d2b36SAndroid Build Coastguard Worker if c.rule.sbox && c.rule.sboxTools { 1126*333d2b36SAndroid Build Coastguard Worker var ret []string 1127*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1128*333d2b36SAndroid Build Coastguard Worker ret = append(ret, filepath.Join(sboxSandboxBaseDir, sboxPathForToolRel(c.rule.ctx, path))) 1129*333d2b36SAndroid Build Coastguard Worker } 1130*333d2b36SAndroid Build Coastguard Worker return ret 1131*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 1132*333d2b36SAndroid Build Coastguard Worker var ret []string 1133*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1134*333d2b36SAndroid Build Coastguard Worker ret = append(ret, nsjailPathForToolRel(c.rule.ctx, path)) 1135*333d2b36SAndroid Build Coastguard Worker } 1136*333d2b36SAndroid Build Coastguard Worker return ret 1137*333d2b36SAndroid Build Coastguard Worker } 1138*333d2b36SAndroid Build Coastguard Worker return paths.Strings() 1139*333d2b36SAndroid Build Coastguard Worker} 1140*333d2b36SAndroid Build Coastguard Worker 1141*333d2b36SAndroid Build Coastguard Worker// PackagedTool adds the specified tool path to the command line. It can only be used with tool 1142*333d2b36SAndroid Build Coastguard Worker// sandboxing enabled by SandboxTools(), and will copy the tool into the sandbox. 1143*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PackagedTool(spec PackagingSpec) *RuleBuilderCommand { 1144*333d2b36SAndroid Build Coastguard Worker c.packagedTools = append(c.packagedTools, spec) 1145*333d2b36SAndroid Build Coastguard Worker if c.rule.sboxTools { 1146*333d2b36SAndroid Build Coastguard Worker c.Text(sboxPathForPackagedToolRel(spec)) 1147*333d2b36SAndroid Build Coastguard Worker } else if c.rule.nsjail { 1148*333d2b36SAndroid Build Coastguard Worker c.Text(nsjailPathForPackagedToolRel(spec)) 1149*333d2b36SAndroid Build Coastguard Worker } else { 1150*333d2b36SAndroid Build Coastguard Worker panic("PackagedTool() requires SandboxTools() or Nsjail()") 1151*333d2b36SAndroid Build Coastguard Worker } 1152*333d2b36SAndroid Build Coastguard Worker return c 1153*333d2b36SAndroid Build Coastguard Worker} 1154*333d2b36SAndroid Build Coastguard Worker 1155*333d2b36SAndroid Build Coastguard Worker// ImplicitPackagedTool copies the specified tool into the sandbox without modifying the command 1156*333d2b36SAndroid Build Coastguard Worker// line. It can only be used with tool sandboxing enabled by SandboxTools(). 1157*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitPackagedTool(spec PackagingSpec) *RuleBuilderCommand { 1158*333d2b36SAndroid Build Coastguard Worker if !c.rule.sboxTools && !c.rule.nsjail { 1159*333d2b36SAndroid Build Coastguard Worker panic("ImplicitPackagedTool() requires SandboxTools() or Nsjail()") 1160*333d2b36SAndroid Build Coastguard Worker } 1161*333d2b36SAndroid Build Coastguard Worker 1162*333d2b36SAndroid Build Coastguard Worker c.packagedTools = append(c.packagedTools, spec) 1163*333d2b36SAndroid Build Coastguard Worker return c 1164*333d2b36SAndroid Build Coastguard Worker} 1165*333d2b36SAndroid Build Coastguard Worker 1166*333d2b36SAndroid Build Coastguard Worker// ImplicitPackagedTools copies the specified tools into the sandbox without modifying the command 1167*333d2b36SAndroid Build Coastguard Worker// line. It can only be used with tool sandboxing enabled by SandboxTools(). 1168*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitPackagedTools(specs []PackagingSpec) *RuleBuilderCommand { 1169*333d2b36SAndroid Build Coastguard Worker if !c.rule.sboxTools && !c.rule.nsjail { 1170*333d2b36SAndroid Build Coastguard Worker panic("ImplicitPackagedTools() requires SandboxTools() or Nsjail()") 1171*333d2b36SAndroid Build Coastguard Worker } 1172*333d2b36SAndroid Build Coastguard Worker 1173*333d2b36SAndroid Build Coastguard Worker c.packagedTools = append(c.packagedTools, specs...) 1174*333d2b36SAndroid Build Coastguard Worker return c 1175*333d2b36SAndroid Build Coastguard Worker} 1176*333d2b36SAndroid Build Coastguard Worker 1177*333d2b36SAndroid Build Coastguard Worker// Text adds the specified raw text to the command line. The text should not contain input or output paths or the 1178*333d2b36SAndroid Build Coastguard Worker// rule will not have them listed in its dependencies or outputs. 1179*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Text(text string) *RuleBuilderCommand { 1180*333d2b36SAndroid Build Coastguard Worker if c.buf.Len() > 0 { 1181*333d2b36SAndroid Build Coastguard Worker c.buf.WriteByte(' ') 1182*333d2b36SAndroid Build Coastguard Worker } 1183*333d2b36SAndroid Build Coastguard Worker c.buf.WriteString(text) 1184*333d2b36SAndroid Build Coastguard Worker return c 1185*333d2b36SAndroid Build Coastguard Worker} 1186*333d2b36SAndroid Build Coastguard Worker 1187*333d2b36SAndroid Build Coastguard Worker// Textf adds the specified formatted text to the command line. The text should not contain input or output paths or 1188*333d2b36SAndroid Build Coastguard Worker// the rule will not have them listed in its dependencies or outputs. 1189*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Textf(format string, a ...interface{}) *RuleBuilderCommand { 1190*333d2b36SAndroid Build Coastguard Worker return c.Text(fmt.Sprintf(format, a...)) 1191*333d2b36SAndroid Build Coastguard Worker} 1192*333d2b36SAndroid Build Coastguard Worker 1193*333d2b36SAndroid Build Coastguard Worker// Flag adds the specified raw text to the command line. The text should not contain input or output paths or the 1194*333d2b36SAndroid Build Coastguard Worker// rule will not have them listed in its dependencies or outputs. 1195*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Flag(flag string) *RuleBuilderCommand { 1196*333d2b36SAndroid Build Coastguard Worker return c.Text(flag) 1197*333d2b36SAndroid Build Coastguard Worker} 1198*333d2b36SAndroid Build Coastguard Worker 1199*333d2b36SAndroid Build Coastguard Worker// OptionalFlag adds the specified raw text to the command line if it is not nil. The text should not contain input or 1200*333d2b36SAndroid Build Coastguard Worker// output paths or the rule will not have them listed in its dependencies or outputs. 1201*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) OptionalFlag(flag *string) *RuleBuilderCommand { 1202*333d2b36SAndroid Build Coastguard Worker if flag != nil { 1203*333d2b36SAndroid Build Coastguard Worker c.Text(*flag) 1204*333d2b36SAndroid Build Coastguard Worker } 1205*333d2b36SAndroid Build Coastguard Worker 1206*333d2b36SAndroid Build Coastguard Worker return c 1207*333d2b36SAndroid Build Coastguard Worker} 1208*333d2b36SAndroid Build Coastguard Worker 1209*333d2b36SAndroid Build Coastguard Worker// Flags adds the specified raw text to the command line. The text should not contain input or output paths or the 1210*333d2b36SAndroid Build Coastguard Worker// rule will not have them listed in its dependencies or outputs. 1211*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Flags(flags []string) *RuleBuilderCommand { 1212*333d2b36SAndroid Build Coastguard Worker for _, flag := range flags { 1213*333d2b36SAndroid Build Coastguard Worker c.Text(flag) 1214*333d2b36SAndroid Build Coastguard Worker } 1215*333d2b36SAndroid Build Coastguard Worker return c 1216*333d2b36SAndroid Build Coastguard Worker} 1217*333d2b36SAndroid Build Coastguard Worker 1218*333d2b36SAndroid Build Coastguard Worker// FlagWithArg adds the specified flag and argument text to the command line, with no separator between them. The flag 1219*333d2b36SAndroid Build Coastguard Worker// and argument should not contain input or output paths or the rule will not have them listed in its dependencies or 1220*333d2b36SAndroid Build Coastguard Worker// outputs. 1221*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithArg(flag, arg string) *RuleBuilderCommand { 1222*333d2b36SAndroid Build Coastguard Worker return c.Text(flag + arg) 1223*333d2b36SAndroid Build Coastguard Worker} 1224*333d2b36SAndroid Build Coastguard Worker 1225*333d2b36SAndroid Build Coastguard Worker// FlagForEachArg adds the specified flag joined with each argument to the command line. The result is identical to 1226*333d2b36SAndroid Build Coastguard Worker// calling FlagWithArg for argument. 1227*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagForEachArg(flag string, args []string) *RuleBuilderCommand { 1228*333d2b36SAndroid Build Coastguard Worker for _, arg := range args { 1229*333d2b36SAndroid Build Coastguard Worker c.FlagWithArg(flag, arg) 1230*333d2b36SAndroid Build Coastguard Worker } 1231*333d2b36SAndroid Build Coastguard Worker return c 1232*333d2b36SAndroid Build Coastguard Worker} 1233*333d2b36SAndroid Build Coastguard Worker 1234*333d2b36SAndroid Build Coastguard Worker// FlagWithList adds the specified flag and list of arguments to the command line, with the arguments joined by sep 1235*333d2b36SAndroid Build Coastguard Worker// and no separator between the flag and arguments. The flag and arguments should not contain input or output paths or 1236*333d2b36SAndroid Build Coastguard Worker// the rule will not have them listed in its dependencies or outputs. 1237*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithList(flag string, list []string, sep string) *RuleBuilderCommand { 1238*333d2b36SAndroid Build Coastguard Worker return c.Text(flag + strings.Join(list, sep)) 1239*333d2b36SAndroid Build Coastguard Worker} 1240*333d2b36SAndroid Build Coastguard Worker 1241*333d2b36SAndroid Build Coastguard Worker// Tool adds the specified tool path to the command line. The path will be also added to the dependencies returned by 1242*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Tools. 1243*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand { 1244*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 1245*333d2b36SAndroid Build Coastguard Worker c.tools = append(c.tools, path) 1246*333d2b36SAndroid Build Coastguard Worker return c.Text(c.PathForTool(path)) 1247*333d2b36SAndroid Build Coastguard Worker} 1248*333d2b36SAndroid Build Coastguard Worker 1249*333d2b36SAndroid Build Coastguard Worker// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools. 1250*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitTool(path Path) *RuleBuilderCommand { 1251*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 1252*333d2b36SAndroid Build Coastguard Worker c.tools = append(c.tools, path) 1253*333d2b36SAndroid Build Coastguard Worker return c 1254*333d2b36SAndroid Build Coastguard Worker} 1255*333d2b36SAndroid Build Coastguard Worker 1256*333d2b36SAndroid Build Coastguard Worker// Tool adds the specified tool path to the dependencies returned by RuleBuilder.Tools. 1257*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitTools(paths Paths) *RuleBuilderCommand { 1258*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1259*333d2b36SAndroid Build Coastguard Worker c.ImplicitTool(path) 1260*333d2b36SAndroid Build Coastguard Worker } 1261*333d2b36SAndroid Build Coastguard Worker return c 1262*333d2b36SAndroid Build Coastguard Worker} 1263*333d2b36SAndroid Build Coastguard Worker 1264*333d2b36SAndroid Build Coastguard Worker// BuiltTool adds the specified tool path that was built using a host Soong module to the command line. The path will 1265*333d2b36SAndroid Build Coastguard Worker// be also added to the dependencies returned by RuleBuilder.Tools. 1266*333d2b36SAndroid Build Coastguard Worker// 1267*333d2b36SAndroid Build Coastguard Worker// It is equivalent to: 1268*333d2b36SAndroid Build Coastguard Worker// 1269*333d2b36SAndroid Build Coastguard Worker// cmd.Tool(ctx.Config().HostToolPath(ctx, tool)) 1270*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) BuiltTool(tool string) *RuleBuilderCommand { 1271*333d2b36SAndroid Build Coastguard Worker if c.rule.ctx.Config().UseHostMusl() { 1272*333d2b36SAndroid Build Coastguard Worker // If the host is using musl, assume that the tool was built against musl libc and include 1273*333d2b36SAndroid Build Coastguard Worker // libc_musl.so in the sandbox. 1274*333d2b36SAndroid Build Coastguard Worker // TODO(ccross): if we supported adding new dependencies during GenerateAndroidBuildActions 1275*333d2b36SAndroid Build Coastguard Worker // this could be a dependency + TransitivePackagingSpecs. 1276*333d2b36SAndroid Build Coastguard Worker c.ImplicitTool(c.rule.ctx.Config().HostJNIToolPath(c.rule.ctx, "libc_musl")) 1277*333d2b36SAndroid Build Coastguard Worker } 1278*333d2b36SAndroid Build Coastguard Worker return c.builtToolWithoutDeps(tool) 1279*333d2b36SAndroid Build Coastguard Worker} 1280*333d2b36SAndroid Build Coastguard Worker 1281*333d2b36SAndroid Build Coastguard Worker// builtToolWithoutDeps is similar to BuiltTool, but doesn't add any dependencies. It is used 1282*333d2b36SAndroid Build Coastguard Worker// internally by RuleBuilder for helper tools that are known to be compiled statically. 1283*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) builtToolWithoutDeps(tool string) *RuleBuilderCommand { 1284*333d2b36SAndroid Build Coastguard Worker return c.Tool(c.rule.ctx.Config().HostToolPath(c.rule.ctx, tool)) 1285*333d2b36SAndroid Build Coastguard Worker} 1286*333d2b36SAndroid Build Coastguard Worker 1287*333d2b36SAndroid Build Coastguard Worker// PrebuiltBuildTool adds the specified tool path from prebuils/build-tools. The path will be also added to the 1288*333d2b36SAndroid Build Coastguard Worker// dependencies returned by RuleBuilder.Tools. 1289*333d2b36SAndroid Build Coastguard Worker// 1290*333d2b36SAndroid Build Coastguard Worker// It is equivalent to: 1291*333d2b36SAndroid Build Coastguard Worker// 1292*333d2b36SAndroid Build Coastguard Worker// cmd.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool)) 1293*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) PrebuiltBuildTool(ctx PathContext, tool string) *RuleBuilderCommand { 1294*333d2b36SAndroid Build Coastguard Worker return c.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool)) 1295*333d2b36SAndroid Build Coastguard Worker} 1296*333d2b36SAndroid Build Coastguard Worker 1297*333d2b36SAndroid Build Coastguard Worker// Input adds the specified input path to the command line. The path will also be added to the dependencies returned by 1298*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Inputs. 1299*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand { 1300*333d2b36SAndroid Build Coastguard Worker return c.Text(c.addInput(path)) 1301*333d2b36SAndroid Build Coastguard Worker} 1302*333d2b36SAndroid Build Coastguard Worker 1303*333d2b36SAndroid Build Coastguard Worker// Inputs adds the specified input paths to the command line, separated by spaces. The paths will also be added to the 1304*333d2b36SAndroid Build Coastguard Worker// dependencies returned by RuleBuilder.Inputs. 1305*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Inputs(paths Paths) *RuleBuilderCommand { 1306*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1307*333d2b36SAndroid Build Coastguard Worker c.Input(path) 1308*333d2b36SAndroid Build Coastguard Worker } 1309*333d2b36SAndroid Build Coastguard Worker return c 1310*333d2b36SAndroid Build Coastguard Worker} 1311*333d2b36SAndroid Build Coastguard Worker 1312*333d2b36SAndroid Build Coastguard Worker// Implicit adds the specified input path to the dependencies returned by RuleBuilder.Inputs without modifying the 1313*333d2b36SAndroid Build Coastguard Worker// command line. 1314*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Implicit(path Path) *RuleBuilderCommand { 1315*333d2b36SAndroid Build Coastguard Worker c.addImplicit(path) 1316*333d2b36SAndroid Build Coastguard Worker return c 1317*333d2b36SAndroid Build Coastguard Worker} 1318*333d2b36SAndroid Build Coastguard Worker 1319*333d2b36SAndroid Build Coastguard Worker// Implicits adds the specified input paths to the dependencies returned by RuleBuilder.Inputs without modifying the 1320*333d2b36SAndroid Build Coastguard Worker// command line. 1321*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand { 1322*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1323*333d2b36SAndroid Build Coastguard Worker c.addImplicit(path) 1324*333d2b36SAndroid Build Coastguard Worker } 1325*333d2b36SAndroid Build Coastguard Worker return c 1326*333d2b36SAndroid Build Coastguard Worker} 1327*333d2b36SAndroid Build Coastguard Worker 1328*333d2b36SAndroid Build Coastguard Worker// ImplicitDirectory adds the specified input directory to the dependencies without modifying the 1329*333d2b36SAndroid Build Coastguard Worker// command line. Added directories will be bind-mounted for the nsjail. 1330*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitDirectory(path DirectoryPath) *RuleBuilderCommand { 1331*333d2b36SAndroid Build Coastguard Worker if !c.rule.nsjail { 1332*333d2b36SAndroid Build Coastguard Worker panic("ImplicitDirectory() must be called after Nsjail()") 1333*333d2b36SAndroid Build Coastguard Worker } 1334*333d2b36SAndroid Build Coastguard Worker c.addImplicitDirectory(path) 1335*333d2b36SAndroid Build Coastguard Worker return c 1336*333d2b36SAndroid Build Coastguard Worker} 1337*333d2b36SAndroid Build Coastguard Worker 1338*333d2b36SAndroid Build Coastguard Worker// GetImplicits returns the command's implicit inputs. 1339*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) GetImplicits() Paths { 1340*333d2b36SAndroid Build Coastguard Worker return c.implicits 1341*333d2b36SAndroid Build Coastguard Worker} 1342*333d2b36SAndroid Build Coastguard Worker 1343*333d2b36SAndroid Build Coastguard Worker// OrderOnly adds the specified input path to the dependencies returned by RuleBuilder.OrderOnlys 1344*333d2b36SAndroid Build Coastguard Worker// without modifying the command line. 1345*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) OrderOnly(path Path) *RuleBuilderCommand { 1346*333d2b36SAndroid Build Coastguard Worker c.addOrderOnly(path) 1347*333d2b36SAndroid Build Coastguard Worker return c 1348*333d2b36SAndroid Build Coastguard Worker} 1349*333d2b36SAndroid Build Coastguard Worker 1350*333d2b36SAndroid Build Coastguard Worker// OrderOnlys adds the specified input paths to the dependencies returned by RuleBuilder.OrderOnlys 1351*333d2b36SAndroid Build Coastguard Worker// without modifying the command line. 1352*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) OrderOnlys(paths Paths) *RuleBuilderCommand { 1353*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1354*333d2b36SAndroid Build Coastguard Worker c.addOrderOnly(path) 1355*333d2b36SAndroid Build Coastguard Worker } 1356*333d2b36SAndroid Build Coastguard Worker return c 1357*333d2b36SAndroid Build Coastguard Worker} 1358*333d2b36SAndroid Build Coastguard Worker 1359*333d2b36SAndroid Build Coastguard Worker// Validation adds the specified input path to the validation dependencies by 1360*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Validations without modifying the command line. 1361*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Validation(path Path) *RuleBuilderCommand { 1362*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 1363*333d2b36SAndroid Build Coastguard Worker c.validations = append(c.validations, path) 1364*333d2b36SAndroid Build Coastguard Worker return c 1365*333d2b36SAndroid Build Coastguard Worker} 1366*333d2b36SAndroid Build Coastguard Worker 1367*333d2b36SAndroid Build Coastguard Worker// Validations adds the specified input paths to the validation dependencies by 1368*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Validations without modifying the command line. 1369*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Validations(paths Paths) *RuleBuilderCommand { 1370*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1371*333d2b36SAndroid Build Coastguard Worker c.Validation(path) 1372*333d2b36SAndroid Build Coastguard Worker } 1373*333d2b36SAndroid Build Coastguard Worker return c 1374*333d2b36SAndroid Build Coastguard Worker} 1375*333d2b36SAndroid Build Coastguard Worker 1376*333d2b36SAndroid Build Coastguard Worker// Output adds the specified output path to the command line. The path will also be added to the outputs returned by 1377*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Outputs. 1378*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand { 1379*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 1380*333d2b36SAndroid Build Coastguard Worker c.outputs = append(c.outputs, path) 1381*333d2b36SAndroid Build Coastguard Worker return c.Text(c.PathForOutput(path)) 1382*333d2b36SAndroid Build Coastguard Worker} 1383*333d2b36SAndroid Build Coastguard Worker 1384*333d2b36SAndroid Build Coastguard Worker// Outputs adds the specified output paths to the command line, separated by spaces. The paths will also be added to 1385*333d2b36SAndroid Build Coastguard Worker// the outputs returned by RuleBuilder.Outputs. 1386*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) Outputs(paths WritablePaths) *RuleBuilderCommand { 1387*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1388*333d2b36SAndroid Build Coastguard Worker c.Output(path) 1389*333d2b36SAndroid Build Coastguard Worker } 1390*333d2b36SAndroid Build Coastguard Worker return c 1391*333d2b36SAndroid Build Coastguard Worker} 1392*333d2b36SAndroid Build Coastguard Worker 1393*333d2b36SAndroid Build Coastguard Worker// OutputDir adds the output directory to the command line. This is only available when used with RuleBuilder.Sbox, 1394*333d2b36SAndroid Build Coastguard Worker// and will be the temporary output directory managed by sbox, not the final one. 1395*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) OutputDir(subPathComponents ...string) *RuleBuilderCommand { 1396*333d2b36SAndroid Build Coastguard Worker if !c.rule.sbox { 1397*333d2b36SAndroid Build Coastguard Worker panic("OutputDir only valid with Sbox") 1398*333d2b36SAndroid Build Coastguard Worker } 1399*333d2b36SAndroid Build Coastguard Worker path := sboxOutDir 1400*333d2b36SAndroid Build Coastguard Worker if len(subPathComponents) > 0 { 1401*333d2b36SAndroid Build Coastguard Worker path = filepath.Join(append([]string{sboxOutDir}, subPathComponents...)...) 1402*333d2b36SAndroid Build Coastguard Worker } 1403*333d2b36SAndroid Build Coastguard Worker return c.Text(path) 1404*333d2b36SAndroid Build Coastguard Worker} 1405*333d2b36SAndroid Build Coastguard Worker 1406*333d2b36SAndroid Build Coastguard Worker// DepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles and adds it to the command 1407*333d2b36SAndroid Build Coastguard Worker// line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles are added to 1408*333d2b36SAndroid Build Coastguard Worker// commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the depfiles together. 1409*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) DepFile(path WritablePath) *RuleBuilderCommand { 1410*333d2b36SAndroid Build Coastguard Worker checkPathNotNil(path) 1411*333d2b36SAndroid Build Coastguard Worker c.depFiles = append(c.depFiles, path) 1412*333d2b36SAndroid Build Coastguard Worker return c.Text(c.PathForOutput(path)) 1413*333d2b36SAndroid Build Coastguard Worker} 1414*333d2b36SAndroid Build Coastguard Worker 1415*333d2b36SAndroid Build Coastguard Worker// ImplicitOutput adds the specified output path to the dependencies returned by RuleBuilder.Outputs without modifying 1416*333d2b36SAndroid Build Coastguard Worker// the command line. 1417*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitOutput(path WritablePath) *RuleBuilderCommand { 1418*333d2b36SAndroid Build Coastguard Worker c.outputs = append(c.outputs, path) 1419*333d2b36SAndroid Build Coastguard Worker return c 1420*333d2b36SAndroid Build Coastguard Worker} 1421*333d2b36SAndroid Build Coastguard Worker 1422*333d2b36SAndroid Build Coastguard Worker// ImplicitOutputs adds the specified output paths to the dependencies returned by RuleBuilder.Outputs without modifying 1423*333d2b36SAndroid Build Coastguard Worker// the command line. 1424*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitOutputs(paths WritablePaths) *RuleBuilderCommand { 1425*333d2b36SAndroid Build Coastguard Worker c.outputs = append(c.outputs, paths...) 1426*333d2b36SAndroid Build Coastguard Worker return c 1427*333d2b36SAndroid Build Coastguard Worker} 1428*333d2b36SAndroid Build Coastguard Worker 1429*333d2b36SAndroid Build Coastguard Worker// ImplicitDepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles without modifying 1430*333d2b36SAndroid Build Coastguard Worker// the command line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles 1431*333d2b36SAndroid Build Coastguard Worker// are added to commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the 1432*333d2b36SAndroid Build Coastguard Worker// depfiles together. 1433*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) ImplicitDepFile(path WritablePath) *RuleBuilderCommand { 1434*333d2b36SAndroid Build Coastguard Worker c.depFiles = append(c.depFiles, path) 1435*333d2b36SAndroid Build Coastguard Worker return c 1436*333d2b36SAndroid Build Coastguard Worker} 1437*333d2b36SAndroid Build Coastguard Worker 1438*333d2b36SAndroid Build Coastguard Worker// FlagWithInput adds the specified flag and input path to the command line, with no separator between them. The path 1439*333d2b36SAndroid Build Coastguard Worker// will also be added to the dependencies returned by RuleBuilder.Inputs. 1440*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithInput(flag string, path Path) *RuleBuilderCommand { 1441*333d2b36SAndroid Build Coastguard Worker return c.Text(flag + c.addInput(path)) 1442*333d2b36SAndroid Build Coastguard Worker} 1443*333d2b36SAndroid Build Coastguard Worker 1444*333d2b36SAndroid Build Coastguard Worker// FlagWithInputList adds the specified flag and input paths to the command line, with the inputs joined by sep 1445*333d2b36SAndroid Build Coastguard Worker// and no separator between the flag and inputs. The input paths will also be added to the dependencies returned by 1446*333d2b36SAndroid Build Coastguard Worker// RuleBuilder.Inputs. 1447*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithInputList(flag string, paths Paths, sep string) *RuleBuilderCommand { 1448*333d2b36SAndroid Build Coastguard Worker strs := make([]string, len(paths)) 1449*333d2b36SAndroid Build Coastguard Worker for i, path := range paths { 1450*333d2b36SAndroid Build Coastguard Worker strs[i] = c.addInput(path) 1451*333d2b36SAndroid Build Coastguard Worker } 1452*333d2b36SAndroid Build Coastguard Worker return c.FlagWithList(flag, strs, sep) 1453*333d2b36SAndroid Build Coastguard Worker} 1454*333d2b36SAndroid Build Coastguard Worker 1455*333d2b36SAndroid Build Coastguard Worker// FlagForEachInput adds the specified flag joined with each input path to the command line. The input paths will also 1456*333d2b36SAndroid Build Coastguard Worker// be added to the dependencies returned by RuleBuilder.Inputs. The result is identical to calling FlagWithInput for 1457*333d2b36SAndroid Build Coastguard Worker// each input path. 1458*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagForEachInput(flag string, paths Paths) *RuleBuilderCommand { 1459*333d2b36SAndroid Build Coastguard Worker for _, path := range paths { 1460*333d2b36SAndroid Build Coastguard Worker c.FlagWithInput(flag, path) 1461*333d2b36SAndroid Build Coastguard Worker } 1462*333d2b36SAndroid Build Coastguard Worker return c 1463*333d2b36SAndroid Build Coastguard Worker} 1464*333d2b36SAndroid Build Coastguard Worker 1465*333d2b36SAndroid Build Coastguard Worker// FlagWithOutput adds the specified flag and output path to the command line, with no separator between them. The path 1466*333d2b36SAndroid Build Coastguard Worker// will also be added to the outputs returned by RuleBuilder.Outputs. 1467*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithOutput(flag string, path WritablePath) *RuleBuilderCommand { 1468*333d2b36SAndroid Build Coastguard Worker c.outputs = append(c.outputs, path) 1469*333d2b36SAndroid Build Coastguard Worker return c.Text(flag + c.PathForOutput(path)) 1470*333d2b36SAndroid Build Coastguard Worker} 1471*333d2b36SAndroid Build Coastguard Worker 1472*333d2b36SAndroid Build Coastguard Worker// FlagWithDepFile adds the specified flag and depfile path to the command line, with no separator between them. The path 1473*333d2b36SAndroid Build Coastguard Worker// will also be added to the outputs returned by RuleBuilder.Outputs. 1474*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithDepFile(flag string, path WritablePath) *RuleBuilderCommand { 1475*333d2b36SAndroid Build Coastguard Worker c.depFiles = append(c.depFiles, path) 1476*333d2b36SAndroid Build Coastguard Worker return c.Text(flag + c.PathForOutput(path)) 1477*333d2b36SAndroid Build Coastguard Worker} 1478*333d2b36SAndroid Build Coastguard Worker 1479*333d2b36SAndroid Build Coastguard Worker// FlagWithRspFileInputList adds the specified flag and path to an rspfile to the command line, with 1480*333d2b36SAndroid Build Coastguard Worker// no separator between them. The paths will be written to the rspfile. If sbox is enabled, the 1481*333d2b36SAndroid Build Coastguard Worker// rspfile must be outside the sbox directory. The first use of FlagWithRspFileInputList in any 1482*333d2b36SAndroid Build Coastguard Worker// RuleBuilderCommand of a RuleBuilder will use Ninja's rsp file support for the rule, additional 1483*333d2b36SAndroid Build Coastguard Worker// uses will result in an auxiliary rules to write the rspFile contents. 1484*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) FlagWithRspFileInputList(flag string, rspFile WritablePath, paths Paths) *RuleBuilderCommand { 1485*333d2b36SAndroid Build Coastguard Worker // Use an empty slice if paths is nil, the non-nil slice is used as an indicator that the rsp file must be 1486*333d2b36SAndroid Build Coastguard Worker // generated. 1487*333d2b36SAndroid Build Coastguard Worker if paths == nil { 1488*333d2b36SAndroid Build Coastguard Worker paths = Paths{} 1489*333d2b36SAndroid Build Coastguard Worker } 1490*333d2b36SAndroid Build Coastguard Worker 1491*333d2b36SAndroid Build Coastguard Worker c.rspFiles = append(c.rspFiles, rspFileAndPaths{rspFile, paths}) 1492*333d2b36SAndroid Build Coastguard Worker 1493*333d2b36SAndroid Build Coastguard Worker if c.rule.sbox { 1494*333d2b36SAndroid Build Coastguard Worker if _, isRel, _ := maybeRelErr(c.rule.outDir.String(), rspFile.String()); isRel { 1495*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("FlagWithRspFileInputList rspfile %q must not be inside out dir %q", 1496*333d2b36SAndroid Build Coastguard Worker rspFile.String(), c.rule.outDir.String())) 1497*333d2b36SAndroid Build Coastguard Worker } 1498*333d2b36SAndroid Build Coastguard Worker } 1499*333d2b36SAndroid Build Coastguard Worker 1500*333d2b36SAndroid Build Coastguard Worker c.FlagWithArg(flag, c.PathForInput(rspFile)) 1501*333d2b36SAndroid Build Coastguard Worker return c 1502*333d2b36SAndroid Build Coastguard Worker} 1503*333d2b36SAndroid Build Coastguard Worker 1504*333d2b36SAndroid Build Coastguard Worker// String returns the command line. 1505*333d2b36SAndroid Build Coastguard Workerfunc (c *RuleBuilderCommand) String() string { 1506*333d2b36SAndroid Build Coastguard Worker return c.buf.String() 1507*333d2b36SAndroid Build Coastguard Worker} 1508*333d2b36SAndroid Build Coastguard Worker 1509*333d2b36SAndroid Build Coastguard Worker// RuleBuilderSboxProtoForTests takes the BuildParams for the manifest passed to RuleBuilder.Sbox() 1510*333d2b36SAndroid Build Coastguard Worker// and returns sbox testproto generated by the RuleBuilder. 1511*333d2b36SAndroid Build Coastguard Workerfunc RuleBuilderSboxProtoForTests(t *testing.T, ctx *TestContext, params TestingBuildParams) *sbox_proto.Manifest { 1512*333d2b36SAndroid Build Coastguard Worker t.Helper() 1513*333d2b36SAndroid Build Coastguard Worker content := ContentFromFileRuleForTests(t, ctx, params) 1514*333d2b36SAndroid Build Coastguard Worker manifest := sbox_proto.Manifest{} 1515*333d2b36SAndroid Build Coastguard Worker err := prototext.Unmarshal([]byte(content), &manifest) 1516*333d2b36SAndroid Build Coastguard Worker if err != nil { 1517*333d2b36SAndroid Build Coastguard Worker t.Fatalf("failed to unmarshal manifest: %s", err.Error()) 1518*333d2b36SAndroid Build Coastguard Worker } 1519*333d2b36SAndroid Build Coastguard Worker return &manifest 1520*333d2b36SAndroid Build Coastguard Worker} 1521*333d2b36SAndroid Build Coastguard Worker 1522*333d2b36SAndroid Build Coastguard Workerfunc ninjaNameEscape(s string) string { 1523*333d2b36SAndroid Build Coastguard Worker b := []byte(s) 1524*333d2b36SAndroid Build Coastguard Worker escaped := false 1525*333d2b36SAndroid Build Coastguard Worker for i, c := range b { 1526*333d2b36SAndroid Build Coastguard Worker valid := (c >= 'a' && c <= 'z') || 1527*333d2b36SAndroid Build Coastguard Worker (c >= 'A' && c <= 'Z') || 1528*333d2b36SAndroid Build Coastguard Worker (c >= '0' && c <= '9') || 1529*333d2b36SAndroid Build Coastguard Worker (c == '_') || 1530*333d2b36SAndroid Build Coastguard Worker (c == '-') || 1531*333d2b36SAndroid Build Coastguard Worker (c == '.') 1532*333d2b36SAndroid Build Coastguard Worker if !valid { 1533*333d2b36SAndroid Build Coastguard Worker b[i] = '_' 1534*333d2b36SAndroid Build Coastguard Worker escaped = true 1535*333d2b36SAndroid Build Coastguard Worker } 1536*333d2b36SAndroid Build Coastguard Worker } 1537*333d2b36SAndroid Build Coastguard Worker if escaped { 1538*333d2b36SAndroid Build Coastguard Worker s = string(b) 1539*333d2b36SAndroid Build Coastguard Worker } 1540*333d2b36SAndroid Build Coastguard Worker return s 1541*333d2b36SAndroid Build Coastguard Worker} 1542*333d2b36SAndroid Build Coastguard Worker 1543*333d2b36SAndroid Build Coastguard Worker// hashSrcFiles returns a hash of the list of source files. It is used to ensure the command line 1544*333d2b36SAndroid Build Coastguard Worker// or the sbox textproto manifest change even if the input files are not listed on the command line. 1545*333d2b36SAndroid Build Coastguard Workerfunc hashSrcFiles(srcFiles Paths) string { 1546*333d2b36SAndroid Build Coastguard Worker h := sha256.New() 1547*333d2b36SAndroid Build Coastguard Worker srcFileList := strings.Join(srcFiles.Strings(), "\n") 1548*333d2b36SAndroid Build Coastguard Worker h.Write([]byte(srcFileList)) 1549*333d2b36SAndroid Build Coastguard Worker return fmt.Sprintf("%x", h.Sum(nil)) 1550*333d2b36SAndroid Build Coastguard Worker} 1551*333d2b36SAndroid Build Coastguard Worker 1552*333d2b36SAndroid Build Coastguard Worker// BuilderContextForTesting returns a BuilderContext for the given config that can be used for tests 1553*333d2b36SAndroid Build Coastguard Worker// that need to call methods that take a BuilderContext. 1554*333d2b36SAndroid Build Coastguard Workerfunc BuilderContextForTesting(config Config) BuilderContext { 1555*333d2b36SAndroid Build Coastguard Worker pathCtx := PathContextForTesting(config) 1556*333d2b36SAndroid Build Coastguard Worker return builderContextForTests{ 1557*333d2b36SAndroid Build Coastguard Worker PathContext: pathCtx, 1558*333d2b36SAndroid Build Coastguard Worker } 1559*333d2b36SAndroid Build Coastguard Worker} 1560*333d2b36SAndroid Build Coastguard Worker 1561*333d2b36SAndroid Build Coastguard Workertype builderContextForTests struct { 1562*333d2b36SAndroid Build Coastguard Worker PathContext 1563*333d2b36SAndroid Build Coastguard Worker} 1564*333d2b36SAndroid Build Coastguard Worker 1565*333d2b36SAndroid Build Coastguard Workerfunc (builderContextForTests) Rule(PackageContext, string, blueprint.RuleParams, ...string) blueprint.Rule { 1566*333d2b36SAndroid Build Coastguard Worker return nil 1567*333d2b36SAndroid Build Coastguard Worker} 1568*333d2b36SAndroid Build Coastguard Workerfunc (builderContextForTests) Build(PackageContext, BuildParams) {} 1569*333d2b36SAndroid Build Coastguard Worker 1570*333d2b36SAndroid Build Coastguard Workerfunc writeRspFileRule(ctx BuilderContext, rspFile WritablePath, paths Paths) { 1571*333d2b36SAndroid Build Coastguard Worker buf := &strings.Builder{} 1572*333d2b36SAndroid Build Coastguard Worker err := response.WriteRspFile(buf, paths.Strings()) 1573*333d2b36SAndroid Build Coastguard Worker if err != nil { 1574*333d2b36SAndroid Build Coastguard Worker // There should never be I/O errors writing to a bytes.Buffer. 1575*333d2b36SAndroid Build Coastguard Worker panic(err) 1576*333d2b36SAndroid Build Coastguard Worker } 1577*333d2b36SAndroid Build Coastguard Worker WriteFileRule(ctx, rspFile, buf.String()) 1578*333d2b36SAndroid Build Coastguard Worker} 1579