blob: 86647eb22ea7ef91c8e017700bd0421a488d60ca [file] [log] [blame]
Colin Crossfeec25b2019-01-30 17:32:39 -08001// Copyright 2019 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
Colin Crossda6401b2021-04-21 11:32:19 -070018 "crypto/sha256"
19 "encoding/hex"
Colin Cross758290d2019-02-01 16:42:32 -080020 "fmt"
Colin Crossfeec25b2019-01-30 17:32:39 -080021 "path/filepath"
Colin Cross3d680512020-11-13 16:23:53 -080022 "regexp"
Colin Cross758290d2019-02-01 16:42:32 -080023 "strings"
Colin Crossfeec25b2019-01-30 17:32:39 -080024 "testing"
Dan Willemsen633c5022019-04-12 11:11:38 -070025
26 "github.com/google/blueprint"
27
28 "android/soong/shared"
Colin Crossfeec25b2019-01-30 17:32:39 -080029)
30
Colin Crossf1a035e2020-11-16 17:32:30 -080031func builderContext() BuilderContext {
32 return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
Colin Cross98be1bb2019-12-13 20:41:13 -080033 "ld": nil,
34 "a.o": nil,
35 "b.o": nil,
36 "cp": nil,
37 "a": nil,
38 "b": nil,
39 "ls": nil,
Jingwen Chence679d22020-09-23 04:30:02 +000040 "ln": nil,
Colin Cross98be1bb2019-12-13 20:41:13 -080041 "turbine": nil,
42 "java": nil,
43 "javac": nil,
44 }))
Colin Cross69f59a32019-02-15 10:39:37 -080045}
46
Colin Cross758290d2019-02-01 16:42:32 -080047func ExampleRuleBuilder() {
Colin Crossf1a035e2020-11-16 17:32:30 -080048 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -080049
Colin Crossf1a035e2020-11-16 17:32:30 -080050 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -080051
52 rule.Command().
53 Tool(PathForSource(ctx, "ld")).
54 Inputs(PathsForTesting("a.o", "b.o")).
55 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -080056 rule.Command().Text("echo success")
57
58 // To add the command to the build graph:
Colin Crossf1a035e2020-11-16 17:32:30 -080059 // rule.Build("link", "link")
Colin Cross758290d2019-02-01 16:42:32 -080060
61 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
62 fmt.Printf("tools: %q\n", rule.Tools())
63 fmt.Printf("inputs: %q\n", rule.Inputs())
64 fmt.Printf("outputs: %q\n", rule.Outputs())
65
66 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -080067 // commands: "ld a.o b.o -o out/soong/linked && echo success"
Colin Cross758290d2019-02-01 16:42:32 -080068 // tools: ["ld"]
69 // inputs: ["a.o" "b.o"]
Colin Cross7b6a55f2021-11-09 12:34:39 -080070 // outputs: ["out/soong/linked"]
Colin Cross758290d2019-02-01 16:42:32 -080071}
72
Jingwen Chence679d22020-09-23 04:30:02 +000073func ExampleRuleBuilder_SymlinkOutputs() {
Colin Crossf1a035e2020-11-16 17:32:30 -080074 ctx := builderContext()
Jingwen Chence679d22020-09-23 04:30:02 +000075
Colin Crossf1a035e2020-11-16 17:32:30 -080076 rule := NewRuleBuilder(pctx, ctx)
Jingwen Chence679d22020-09-23 04:30:02 +000077
78 rule.Command().
79 Tool(PathForSource(ctx, "ln")).
80 FlagWithInput("-s ", PathForTesting("a.o")).
81 SymlinkOutput(PathForOutput(ctx, "a"))
Colin Cross7b6a55f2021-11-09 12:34:39 -080082 rule.Command().Text("cp out/soong/a out/soong/b").
Jingwen Chence679d22020-09-23 04:30:02 +000083 ImplicitSymlinkOutput(PathForOutput(ctx, "b"))
84
85 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
86 fmt.Printf("tools: %q\n", rule.Tools())
87 fmt.Printf("inputs: %q\n", rule.Inputs())
88 fmt.Printf("outputs: %q\n", rule.Outputs())
89 fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs())
90
91 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -080092 // commands: "ln -s a.o out/soong/a && cp out/soong/a out/soong/b"
Jingwen Chence679d22020-09-23 04:30:02 +000093 // tools: ["ln"]
94 // inputs: ["a.o"]
Colin Cross7b6a55f2021-11-09 12:34:39 -080095 // outputs: ["out/soong/a" "out/soong/b"]
96 // symlink_outputs: ["out/soong/a" "out/soong/b"]
Jingwen Chence679d22020-09-23 04:30:02 +000097}
98
Colin Cross5cb5b092019-02-02 21:25:18 -080099func ExampleRuleBuilder_Temporary() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800100 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -0800101
Colin Crossf1a035e2020-11-16 17:32:30 -0800102 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800103
104 rule.Command().
105 Tool(PathForSource(ctx, "cp")).
106 Input(PathForSource(ctx, "a")).
107 Output(PathForOutput(ctx, "b"))
108 rule.Command().
109 Tool(PathForSource(ctx, "cp")).
110 Input(PathForOutput(ctx, "b")).
111 Output(PathForOutput(ctx, "c"))
112 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -0800113
114 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
115 fmt.Printf("tools: %q\n", rule.Tools())
116 fmt.Printf("inputs: %q\n", rule.Inputs())
117 fmt.Printf("outputs: %q\n", rule.Outputs())
118
119 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800120 // commands: "cp a out/soong/b && cp out/soong/b out/soong/c"
Colin Cross5cb5b092019-02-02 21:25:18 -0800121 // tools: ["cp"]
122 // inputs: ["a"]
Colin Cross7b6a55f2021-11-09 12:34:39 -0800123 // outputs: ["out/soong/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800124}
125
126func ExampleRuleBuilder_DeleteTemporaryFiles() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800127 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -0800128
Colin Crossf1a035e2020-11-16 17:32:30 -0800129 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800130
131 rule.Command().
132 Tool(PathForSource(ctx, "cp")).
133 Input(PathForSource(ctx, "a")).
134 Output(PathForOutput(ctx, "b"))
135 rule.Command().
136 Tool(PathForSource(ctx, "cp")).
137 Input(PathForOutput(ctx, "b")).
138 Output(PathForOutput(ctx, "c"))
139 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -0800140 rule.DeleteTemporaryFiles()
141
142 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
143 fmt.Printf("tools: %q\n", rule.Tools())
144 fmt.Printf("inputs: %q\n", rule.Inputs())
145 fmt.Printf("outputs: %q\n", rule.Outputs())
146
147 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800148 // commands: "cp a out/soong/b && cp out/soong/b out/soong/c && rm -f out/soong/b"
Colin Cross5cb5b092019-02-02 21:25:18 -0800149 // tools: ["cp"]
150 // inputs: ["a"]
Colin Cross7b6a55f2021-11-09 12:34:39 -0800151 // outputs: ["out/soong/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800152}
153
Colin Crossdeabb942019-02-11 14:11:09 -0800154func ExampleRuleBuilder_Installs() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800155 ctx := builderContext()
Colin Crossdeabb942019-02-11 14:11:09 -0800156
Colin Crossf1a035e2020-11-16 17:32:30 -0800157 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800158
159 out := PathForOutput(ctx, "linked")
160
161 rule.Command().
162 Tool(PathForSource(ctx, "ld")).
163 Inputs(PathsForTesting("a.o", "b.o")).
164 FlagWithOutput("-o ", out)
165 rule.Install(out, "/bin/linked")
166 rule.Install(out, "/sbin/linked")
Colin Crossdeabb942019-02-11 14:11:09 -0800167
168 fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
169
170 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800171 // rule.Installs().String() = "out/soong/linked:/bin/linked out/soong/linked:/sbin/linked"
Colin Crossdeabb942019-02-11 14:11:09 -0800172}
173
Colin Cross758290d2019-02-01 16:42:32 -0800174func ExampleRuleBuilderCommand() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800175 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -0800176
Colin Crossf1a035e2020-11-16 17:32:30 -0800177 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800178
Colin Cross758290d2019-02-01 16:42:32 -0800179 // chained
Colin Cross69f59a32019-02-15 10:39:37 -0800180 rule.Command().
181 Tool(PathForSource(ctx, "ld")).
182 Inputs(PathsForTesting("a.o", "b.o")).
183 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800184
185 // unchained
186 cmd := rule.Command()
Colin Cross69f59a32019-02-15 10:39:37 -0800187 cmd.Tool(PathForSource(ctx, "ld"))
188 cmd.Inputs(PathsForTesting("a.o", "b.o"))
189 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800190
191 // mixed:
Colin Cross69f59a32019-02-15 10:39:37 -0800192 cmd = rule.Command().Tool(PathForSource(ctx, "ld"))
193 cmd.Inputs(PathsForTesting("a.o", "b.o"))
194 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800195}
196
197func ExampleRuleBuilderCommand_Flag() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800198 ctx := builderContext()
199 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800200 Tool(PathForSource(ctx, "ls")).Flag("-l"))
Colin Cross758290d2019-02-01 16:42:32 -0800201 // Output:
202 // ls -l
203}
204
Colin Cross92b7d582019-03-29 15:32:51 -0700205func ExampleRuleBuilderCommand_Flags() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800206 ctx := builderContext()
207 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross92b7d582019-03-29 15:32:51 -0700208 Tool(PathForSource(ctx, "ls")).Flags([]string{"-l", "-a"}))
209 // Output:
210 // ls -l -a
211}
212
Colin Cross758290d2019-02-01 16:42:32 -0800213func ExampleRuleBuilderCommand_FlagWithArg() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800214 ctx := builderContext()
215 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800216 Tool(PathForSource(ctx, "ls")).
Colin Cross758290d2019-02-01 16:42:32 -0800217 FlagWithArg("--sort=", "time"))
218 // Output:
219 // ls --sort=time
220}
221
Colin Crossc7ed0042019-02-11 14:11:09 -0800222func ExampleRuleBuilderCommand_FlagForEachArg() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800223 ctx := builderContext()
224 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800225 Tool(PathForSource(ctx, "ls")).
Colin Crossc7ed0042019-02-11 14:11:09 -0800226 FlagForEachArg("--sort=", []string{"time", "size"}))
227 // Output:
228 // ls --sort=time --sort=size
229}
230
Colin Cross758290d2019-02-01 16:42:32 -0800231func ExampleRuleBuilderCommand_FlagForEachInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800232 ctx := builderContext()
233 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800234 Tool(PathForSource(ctx, "turbine")).
235 FlagForEachInput("--classpath ", PathsForTesting("a.jar", "b.jar")))
Colin Cross758290d2019-02-01 16:42:32 -0800236 // Output:
237 // turbine --classpath a.jar --classpath b.jar
238}
239
240func ExampleRuleBuilderCommand_FlagWithInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800241 ctx := builderContext()
242 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800243 Tool(PathForSource(ctx, "java")).
244 FlagWithInputList("-classpath=", PathsForTesting("a.jar", "b.jar"), ":"))
Colin Cross758290d2019-02-01 16:42:32 -0800245 // Output:
246 // java -classpath=a.jar:b.jar
247}
248
249func ExampleRuleBuilderCommand_FlagWithInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800250 ctx := builderContext()
251 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800252 Tool(PathForSource(ctx, "java")).
253 FlagWithInput("-classpath=", PathForSource(ctx, "a")))
Colin Cross758290d2019-02-01 16:42:32 -0800254 // Output:
255 // java -classpath=a
256}
257
258func ExampleRuleBuilderCommand_FlagWithList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800259 ctx := builderContext()
260 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800261 Tool(PathForSource(ctx, "ls")).
Colin Cross758290d2019-02-01 16:42:32 -0800262 FlagWithList("--sort=", []string{"time", "size"}, ","))
263 // Output:
264 // ls --sort=time,size
265}
266
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700267func ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800268 ctx := builderContext()
269 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700270 Tool(PathForSource(ctx, "javac")).
Colin Cross70c47412021-03-12 17:48:14 -0800271 FlagWithRspFileInputList("@", PathForOutput(ctx, "foo.rsp"), PathsForTesting("a.java", "b.java")).
272 String())
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700273 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800274 // javac @out/soong/foo.rsp
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700275}
276
277func ExampleRuleBuilderCommand_String() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800278 ctx := builderContext()
279 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700280 Text("FOO=foo").
281 Text("echo $FOO").
282 String())
283 // Output:
284 // FOO=foo echo $FOO
285}
286
Colin Crossfeec25b2019-01-30 17:32:39 -0800287func TestRuleBuilder(t *testing.T) {
Colin Cross69f59a32019-02-15 10:39:37 -0800288 fs := map[string][]byte{
Colin Crossda71eda2020-02-21 16:55:19 -0800289 "dep_fixer": nil,
290 "input": nil,
291 "Implicit": nil,
292 "Input": nil,
293 "OrderOnly": nil,
294 "OrderOnlys": nil,
295 "Tool": nil,
296 "input2": nil,
297 "tool2": nil,
298 "input3": nil,
Colin Cross69f59a32019-02-15 10:39:37 -0800299 }
300
Colin Crossab020a72021-03-12 17:52:23 -0800301 pathCtx := PathContextForTesting(TestConfig("out_local", nil, "", fs))
Colin Crossf1a035e2020-11-16 17:32:30 -0800302 ctx := builderContextForTests{
303 PathContext: pathCtx,
304 }
Colin Cross69f59a32019-02-15 10:39:37 -0800305
Dan Willemsen633c5022019-04-12 11:11:38 -0700306 addCommands := func(rule *RuleBuilder) {
307 cmd := rule.Command().
Colin Crossab020a72021-03-12 17:52:23 -0800308 DepFile(PathForOutput(ctx, "module/DepFile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700309 Flag("Flag").
310 FlagWithArg("FlagWithArg=", "arg").
Colin Crossab020a72021-03-12 17:52:23 -0800311 FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "module/depfile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700312 FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
Colin Crossab020a72021-03-12 17:52:23 -0800313 FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "module/output")).
314 FlagWithRspFileInputList("FlagWithRspFileInputList=", PathForOutput(ctx, "rsp"),
315 Paths{
316 PathForSource(ctx, "RspInput"),
317 PathForOutput(ctx, "other/RspOutput2"),
318 }).
Dan Willemsen633c5022019-04-12 11:11:38 -0700319 Implicit(PathForSource(ctx, "Implicit")).
Colin Crossab020a72021-03-12 17:52:23 -0800320 ImplicitDepFile(PathForOutput(ctx, "module/ImplicitDepFile")).
321 ImplicitOutput(PathForOutput(ctx, "module/ImplicitOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700322 Input(PathForSource(ctx, "Input")).
Colin Crossab020a72021-03-12 17:52:23 -0800323 Output(PathForOutput(ctx, "module/Output")).
Colin Crossda71eda2020-02-21 16:55:19 -0800324 OrderOnly(PathForSource(ctx, "OrderOnly")).
Colin Crossae89abe2021-04-21 11:45:23 -0700325 Validation(PathForSource(ctx, "Validation")).
Colin Crossab020a72021-03-12 17:52:23 -0800326 SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")).
327 ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700328 Text("Text").
329 Tool(PathForSource(ctx, "Tool"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800330
Dan Willemsen633c5022019-04-12 11:11:38 -0700331 rule.Command().
332 Text("command2").
Colin Crossab020a72021-03-12 17:52:23 -0800333 DepFile(PathForOutput(ctx, "module/depfile2")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700334 Input(PathForSource(ctx, "input2")).
Colin Crossab020a72021-03-12 17:52:23 -0800335 Output(PathForOutput(ctx, "module/output2")).
Colin Crossda71eda2020-02-21 16:55:19 -0800336 OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Colin Crossae89abe2021-04-21 11:45:23 -0700337 Validations(PathsForSource(ctx, []string{"Validations"})).
Dan Willemsen633c5022019-04-12 11:11:38 -0700338 Tool(PathForSource(ctx, "tool2"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800339
Dan Willemsen633c5022019-04-12 11:11:38 -0700340 // Test updates to the first command after the second command has been started
341 cmd.Text("after command2")
342 // Test updating a command when the previous update did not replace the cmd variable
343 cmd.Text("old cmd")
Colin Crossfeec25b2019-01-30 17:32:39 -0800344
Dan Willemsen633c5022019-04-12 11:11:38 -0700345 // Test a command that uses the output of a previous command as an input
346 rule.Command().
347 Text("command3").
348 Input(PathForSource(ctx, "input3")).
Colin Crossab020a72021-03-12 17:52:23 -0800349 Input(PathForOutput(ctx, "module/output2")).
350 Output(PathForOutput(ctx, "module/output3")).
351 Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
352 Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
Colin Crossfeec25b2019-01-30 17:32:39 -0800353 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700354
Colin Cross69f59a32019-02-15 10:39:37 -0800355 wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
Colin Crossab020a72021-03-12 17:52:23 -0800356 wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
357 PathForOutput(ctx, "other/RspOutput2")}
358 wantOutputs := PathsForOutput(ctx, []string{
359 "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput",
360 "module/output", "module/output2", "module/output3"})
361 wantDepFiles := PathsForOutput(ctx, []string{
362 "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
Colin Cross69f59a32019-02-15 10:39:37 -0800363 wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
Colin Crossda71eda2020-02-21 16:55:19 -0800364 wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
Colin Crossae89abe2021-04-21 11:45:23 -0700365 wantValidations := PathsForSource(ctx, []string{"Validation", "Validations"})
Colin Crossab020a72021-03-12 17:52:23 -0800366 wantSymlinkOutputs := PathsForOutput(ctx, []string{
367 "module/ImplicitSymlinkOutput", "module/SymlinkOutput"})
Colin Crossfeec25b2019-01-30 17:32:39 -0800368
Dan Willemsen633c5022019-04-12 11:11:38 -0700369 t.Run("normal", func(t *testing.T) {
Colin Crossf1a035e2020-11-16 17:32:30 -0800370 rule := NewRuleBuilder(pctx, ctx)
Dan Willemsen633c5022019-04-12 11:11:38 -0700371 addCommands(rule)
Colin Cross1d2cf042019-03-29 15:33:06 -0700372
Dan Willemsen633c5022019-04-12 11:11:38 -0700373 wantCommands := []string{
Colin Cross7b6a55f2021-11-09 12:34:39 -0800374 "out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " +
375 "FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " +
376 "Input out_local/soong/module/Output out_local/soong/module/SymlinkOutput Text Tool after command2 old cmd",
377 "command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2",
378 "command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2",
Dan Willemsen633c5022019-04-12 11:11:38 -0700379 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700380
Colin Cross7b6a55f2021-11-09 12:34:39 -0800381 wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
382 "out_local/soong/module/DepFile out_local/soong/module/depfile out_local/soong/module/ImplicitDepFile out_local/soong/module/depfile2"
Colin Crossab020a72021-03-12 17:52:23 -0800383
Paul Duffind250ff62021-03-16 21:51:29 +0000384 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700385
Paul Duffind250ff62021-03-16 21:51:29 +0000386 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800387 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000388 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
389 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
390 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
391 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
392 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700393 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Dan Willemsen633c5022019-04-12 11:11:38 -0700394
Paul Duffind250ff62021-03-16 21:51:29 +0000395 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700396 })
397
398 t.Run("sbox", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800399 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crosse16ce362020-11-12 08:29:30 -0800400 PathForOutput(ctx, "sbox.textproto"))
Dan Willemsen633c5022019-04-12 11:11:38 -0700401 addCommands(rule)
402
403 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800404 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
405 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800406 "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
Colin Crossab020a72021-03-12 17:52:23 -0800407 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
Colin Crosse16ce362020-11-12 08:29:30 -0800408 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
Colin Crossab020a72021-03-12 17:52:23 -0800409 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
Dan Willemsen633c5022019-04-12 11:11:38 -0700410 }
411
Colin Cross7b6a55f2021-11-09 12:34:39 -0800412 wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
Colin Crossab020a72021-03-12 17:52:23 -0800413
Paul Duffind250ff62021-03-16 21:51:29 +0000414 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700415
Paul Duffind250ff62021-03-16 21:51:29 +0000416 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800417 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000418 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800419 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000420 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
421 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
422 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700423 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Dan Willemsen633c5022019-04-12 11:11:38 -0700424
Paul Duffind250ff62021-03-16 21:51:29 +0000425 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700426 })
Colin Crossba9e4032020-11-24 16:32:22 -0800427
428 t.Run("sbox tools", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800429 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crossba9e4032020-11-24 16:32:22 -0800430 PathForOutput(ctx, "sbox.textproto")).SandboxTools()
431 addCommands(rule)
432
433 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800434 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
435 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800436 "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
Colin Crossab020a72021-03-12 17:52:23 -0800437 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
Colin Crossba9e4032020-11-24 16:32:22 -0800438 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
Colin Crossab020a72021-03-12 17:52:23 -0800439 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
Colin Crossba9e4032020-11-24 16:32:22 -0800440 }
441
442 wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
443
Paul Duffind250ff62021-03-16 21:51:29 +0000444 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Colin Crossba9e4032020-11-24 16:32:22 -0800445
Paul Duffind250ff62021-03-16 21:51:29 +0000446 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800447 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000448 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800449 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000450 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
451 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
452 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700453 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Colin Crossba9e4032020-11-24 16:32:22 -0800454
Paul Duffind250ff62021-03-16 21:51:29 +0000455 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Colin Crossba9e4032020-11-24 16:32:22 -0800456 })
Colin Cross045bfd92021-03-24 16:38:03 -0700457
458 t.Run("sbox inputs", func(t *testing.T) {
459 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
460 PathForOutput(ctx, "sbox.textproto")).SandboxInputs()
461 addCommands(rule)
462
463 wantCommands := []string{
464 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
465 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
466 "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
467 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
468 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
469 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
470 }
471
472 wantDepMergerCommand := "__SBOX_SANDBOX_DIR__/tools/out/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
473
474 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
475
476 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
477 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
478 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
479 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
480 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
481 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
482 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700483 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Colin Cross045bfd92021-03-24 16:38:03 -0700484
485 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
486 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800487}
488
489func testRuleBuilderFactory() Module {
490 module := &testRuleBuilderModule{}
491 module.AddProperties(&module.properties)
492 InitAndroidModule(module)
493 return module
494}
495
496type testRuleBuilderModule struct {
497 ModuleBase
498 properties struct {
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000499 Srcs []string
Dan Willemsen633c5022019-04-12 11:11:38 -0700500
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000501 Restat bool
502 Sbox bool
503 Sbox_inputs bool
Colin Crossfeec25b2019-01-30 17:32:39 -0800504 }
505}
506
507func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross3d680512020-11-13 16:23:53 -0800508 in := PathsForSource(ctx, t.properties.Srcs)
Colin Crossda6401b2021-04-21 11:32:19 -0700509 implicit := PathForSource(ctx, "implicit")
510 orderOnly := PathForSource(ctx, "orderonly")
Colin Crossae89abe2021-04-21 11:45:23 -0700511 validation := PathForSource(ctx, "validation")
Colin Crosse16ce362020-11-12 08:29:30 -0800512 out := PathForModuleOut(ctx, "gen", ctx.ModuleName())
513 outDep := PathForModuleOut(ctx, "gen", ctx.ModuleName()+".d")
514 outDir := PathForModuleOut(ctx, "gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700515 rspFile := PathForModuleOut(ctx, "rsp")
516 rspFile2 := PathForModuleOut(ctx, "rsp2")
517 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
518 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800519 manifestPath := PathForModuleOut(ctx, "sbox.textproto")
Colin Crossfeec25b2019-01-30 17:32:39 -0800520
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000521 testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir,
522 manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs,
Colin Crossda6401b2021-04-21 11:32:19 -0700523 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800524}
525
526type testRuleBuilderSingleton struct{}
527
528func testRuleBuilderSingletonFactory() Singleton {
529 return &testRuleBuilderSingleton{}
530}
531
532func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
Colin Crossda6401b2021-04-21 11:32:19 -0700533 in := PathsForSource(ctx, []string{"in"})
534 implicit := PathForSource(ctx, "implicit")
535 orderOnly := PathForSource(ctx, "orderonly")
Colin Crossae89abe2021-04-21 11:45:23 -0700536 validation := PathForSource(ctx, "validation")
Colin Crosse16ce362020-11-12 08:29:30 -0800537 out := PathForOutput(ctx, "singleton/gen/baz")
538 outDep := PathForOutput(ctx, "singleton/gen/baz.d")
539 outDir := PathForOutput(ctx, "singleton/gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700540 rspFile := PathForOutput(ctx, "singleton/rsp")
541 rspFile2 := PathForOutput(ctx, "singleton/rsp2")
542 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
543 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800544 manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
Colin Crossda6401b2021-04-21 11:32:19 -0700545
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000546 testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir,
547 manifestPath, true, false, false,
Colin Crossce3a51d2021-03-19 16:22:12 -0700548 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800549}
550
Colin Crossae89abe2021-04-21 11:45:23 -0700551func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path,
Colin Crossda6401b2021-04-21 11:32:19 -0700552 out, outDep, outDir, manifestPath WritablePath,
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000553 restat, sbox, sboxInputs bool,
Colin Crossce3a51d2021-03-19 16:22:12 -0700554 rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
555
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000556 rule := NewRuleBuilder(pctx, ctx)
Colin Cross786cd6d2019-02-01 16:41:11 -0800557
Dan Willemsen633c5022019-04-12 11:11:38 -0700558 if sbox {
Colin Crosse16ce362020-11-12 08:29:30 -0800559 rule.Sbox(outDir, manifestPath)
Colin Crossce3a51d2021-03-19 16:22:12 -0700560 if sboxInputs {
561 rule.SandboxInputs()
562 }
Dan Willemsen633c5022019-04-12 11:11:38 -0700563 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800564
Colin Crossce3a51d2021-03-19 16:22:12 -0700565 rule.Command().
566 Tool(PathForSource(ctx, "cp")).
567 Inputs(in).
Colin Crossda6401b2021-04-21 11:32:19 -0700568 Implicit(implicit).
569 OrderOnly(orderOnly).
Colin Crossae89abe2021-04-21 11:45:23 -0700570 Validation(validation).
Colin Crossce3a51d2021-03-19 16:22:12 -0700571 Output(out).
572 ImplicitDepFile(outDep).
573 FlagWithRspFileInputList("@", rspFile, rspFileContents).
574 FlagWithRspFileInputList("@", rspFile2, rspFileContents2)
Dan Willemsen633c5022019-04-12 11:11:38 -0700575
576 if restat {
577 rule.Restat()
578 }
Colin Crossbaa676f2019-02-25 14:56:01 -0800579
Wen-yi Chu789a7e02023-09-22 03:58:59 +0000580 rule.Build("rule", "desc")
Colin Crossfeec25b2019-01-30 17:32:39 -0800581}
582
Paul Duffind250ff62021-03-16 21:51:29 +0000583var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
584 ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
585 ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
586})
587
Colin Crossfeec25b2019-01-30 17:32:39 -0800588func TestRuleBuilder_Build(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000589 fs := MockFS{
Colin Crossda6401b2021-04-21 11:32:19 -0700590 "in": nil,
591 "cp": nil,
Colin Cross98be1bb2019-12-13 20:41:13 -0800592 }
593
Colin Crossfeec25b2019-01-30 17:32:39 -0800594 bp := `
595 rule_builder_test {
596 name: "foo",
Colin Crossda6401b2021-04-21 11:32:19 -0700597 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700598 restat: true,
599 }
600 rule_builder_test {
601 name: "foo_sbox",
Colin Crossda6401b2021-04-21 11:32:19 -0700602 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700603 sbox: true,
Colin Crossfeec25b2019-01-30 17:32:39 -0800604 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700605 rule_builder_test {
606 name: "foo_sbox_inputs",
Colin Crossda6401b2021-04-21 11:32:19 -0700607 srcs: ["in"],
Colin Crossce3a51d2021-03-19 16:22:12 -0700608 sbox: true,
609 sbox_inputs: true,
610 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800611 `
612
Paul Duffin30ac3e72021-03-20 00:36:14 +0000613 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000614 prepareForRuleBuilderTest,
615 FixtureWithRootAndroidBp(bp),
616 fs.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000617 ).RunTest(t)
Colin Crossfeec25b2019-01-30 17:32:39 -0800618
Colin Crossce3a51d2021-03-19 16:22:12 -0700619 check := func(t *testing.T, params TestingBuildParams, rspFile2Params TestingBuildParams,
620 wantCommand, wantOutput, wantDepfile, wantRspFile, wantRspFile2 string,
621 wantRestat bool, extraImplicits, extraCmdDeps []string) {
622
Dan Willemsenc89b6f12019-08-29 14:47:40 -0700623 t.Helper()
Colin Cross3d680512020-11-13 16:23:53 -0800624 command := params.RuleParams.Command
Colin Crosse16ce362020-11-12 08:29:30 -0800625 re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
Colin Cross3d680512020-11-13 16:23:53 -0800626 command = re.ReplaceAllLiteralString(command, "")
Paul Duffind250ff62021-03-16 21:51:29 +0000627
628 AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
Dan Willemsen633c5022019-04-12 11:11:38 -0700629
630 wantDeps := append([]string{"cp"}, extraCmdDeps...)
Paul Duffind250ff62021-03-16 21:51:29 +0000631 AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
Dan Willemsen633c5022019-04-12 11:11:38 -0700632
Paul Duffind250ff62021-03-16 21:51:29 +0000633 AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
Colin Crossfeec25b2019-01-30 17:32:39 -0800634
Colin Crossce3a51d2021-03-19 16:22:12 -0700635 wantInputs := []string{"rsp_in"}
636 AssertArrayString(t, "Inputs", wantInputs, params.Inputs.Strings())
637
Colin Crossda6401b2021-04-21 11:32:19 -0700638 wantImplicits := append([]string{"implicit", "in"}, extraImplicits...)
Colin Crossce3a51d2021-03-19 16:22:12 -0700639 // The second rsp file and the files listed in it should be in implicits
640 wantImplicits = append(wantImplicits, "rsp_in2", wantRspFile2)
Paul Duffin709e0e32021-03-22 10:09:02 +0000641 AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
Colin Crossfeec25b2019-01-30 17:32:39 -0800642
Colin Crossda6401b2021-04-21 11:32:19 -0700643 wantOrderOnlys := []string{"orderonly"}
644 AssertPathsRelativeToTopEquals(t, "OrderOnly", wantOrderOnlys, params.OrderOnly)
645
Colin Crossae89abe2021-04-21 11:45:23 -0700646 wantValidations := []string{"validation"}
647 AssertPathsRelativeToTopEquals(t, "Validations", wantValidations, params.Validations)
648
Colin Crossce3a51d2021-03-19 16:22:12 -0700649 wantRspFileContent := "$in"
650 AssertStringEquals(t, "RspfileContent", wantRspFileContent, params.RuleParams.RspfileContent)
651
652 AssertStringEquals(t, "Rspfile", wantRspFile, params.RuleParams.Rspfile)
653
Paul Duffin709e0e32021-03-22 10:09:02 +0000654 AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
Colin Crossbaa676f2019-02-25 14:56:01 -0800655
Dan Willemsen633c5022019-04-12 11:11:38 -0700656 if len(params.ImplicitOutputs) != 0 {
657 t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
658 }
659
Paul Duffin709e0e32021-03-22 10:09:02 +0000660 AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
Dan Willemsen633c5022019-04-12 11:11:38 -0700661
662 if params.Deps != blueprint.DepsGCC {
663 t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
Colin Crossbaa676f2019-02-25 14:56:01 -0800664 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700665
666 rspFile2Content := ContentFromFileRuleForTests(t, rspFile2Params)
667 AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
Colin Crossfeec25b2019-01-30 17:32:39 -0800668 }
669
Colin Cross4c83e5c2019-02-25 14:54:28 -0800670 t.Run("module", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000671 outFile := "out/soong/.intermediates/foo/gen/foo"
Colin Crossce3a51d2021-03-19 16:22:12 -0700672 rspFile := "out/soong/.intermediates/foo/rsp"
673 rspFile2 := "out/soong/.intermediates/foo/rsp2"
674 module := result.ModuleForTests("foo", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100675 check(t, module.Rule("rule"), module.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700676 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700677 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Dan Willemsen633c5022019-04-12 11:11:38 -0700678 })
679 t.Run("sbox", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000680 outDir := "out/soong/.intermediates/foo_sbox"
Colin Crosse52c2ac2022-03-28 17:03:35 -0700681 sboxOutDir := filepath.Join(outDir, "gen")
682 outFile := filepath.Join(sboxOutDir, "foo_sbox")
683 depFile := filepath.Join(sboxOutDir, "foo_sbox.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700684 rspFile := filepath.Join(outDir, "rsp")
685 rspFile2 := filepath.Join(outDir, "rsp2")
686 manifest := filepath.Join(outDir, "sbox.textproto")
687 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
688 sandboxPath := shared.TempDirForOutDir("out/soong")
689
Colin Crosse52c2ac2022-03-28 17:03:35 -0700690 cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
Colin Crossce3a51d2021-03-19 16:22:12 -0700691 module := result.ModuleForTests("foo_sbox", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100692 check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700693 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
694 })
695 t.Run("sbox_inputs", func(t *testing.T) {
696 outDir := "out/soong/.intermediates/foo_sbox_inputs"
Colin Crosse52c2ac2022-03-28 17:03:35 -0700697 sboxOutDir := filepath.Join(outDir, "gen")
698 outFile := filepath.Join(sboxOutDir, "foo_sbox_inputs")
699 depFile := filepath.Join(sboxOutDir, "foo_sbox_inputs.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700700 rspFile := filepath.Join(outDir, "rsp")
701 rspFile2 := filepath.Join(outDir, "rsp2")
Colin Crosse16ce362020-11-12 08:29:30 -0800702 manifest := filepath.Join(outDir, "sbox.textproto")
Paul Duffin709e0e32021-03-22 10:09:02 +0000703 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
704 sandboxPath := shared.TempDirForOutDir("out/soong")
Dan Willemsen633c5022019-04-12 11:11:38 -0700705
Colin Crosse52c2ac2022-03-28 17:03:35 -0700706 cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
Dan Willemsen633c5022019-04-12 11:11:38 -0700707
Colin Crossce3a51d2021-03-19 16:22:12 -0700708 module := result.ModuleForTests("foo_sbox_inputs", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100709 check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700710 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
Colin Cross4c83e5c2019-02-25 14:54:28 -0800711 })
712 t.Run("singleton", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000713 outFile := filepath.Join("out/soong/singleton/gen/baz")
Colin Crossce3a51d2021-03-19 16:22:12 -0700714 rspFile := filepath.Join("out/soong/singleton/rsp")
715 rspFile2 := filepath.Join("out/soong/singleton/rsp2")
716 singleton := result.SingletonForTests("rule_builder_test")
Paul Duffina71a67a2021-03-29 00:42:57 +0100717 check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700718 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700719 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Colin Cross4c83e5c2019-02-25 14:54:28 -0800720 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800721}
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700722
Colin Cross3d680512020-11-13 16:23:53 -0800723func TestRuleBuilderHashInputs(t *testing.T) {
724 // The basic idea here is to verify that the command (in the case of a
725 // non-sbox rule) or the sbox textproto manifest contain a hash of the
726 // inputs.
727
728 // By including a hash of the inputs, we cause the rule to re-run if
729 // the list of inputs changes because the command line or a dependency
730 // changes.
731
Colin Crossda6401b2021-04-21 11:32:19 -0700732 hashOf := func(s string) string {
733 sum := sha256.Sum256([]byte(s))
734 return hex.EncodeToString(sum[:])
735 }
736
Colin Cross3d680512020-11-13 16:23:53 -0800737 bp := `
738 rule_builder_test {
739 name: "hash0",
740 srcs: ["in1.txt", "in2.txt"],
741 }
742 rule_builder_test {
743 name: "hash0_sbox",
744 srcs: ["in1.txt", "in2.txt"],
745 sbox: true,
746 }
747 rule_builder_test {
748 name: "hash1",
749 srcs: ["in1.txt", "in2.txt", "in3.txt"],
750 }
751 rule_builder_test {
752 name: "hash1_sbox",
753 srcs: ["in1.txt", "in2.txt", "in3.txt"],
754 sbox: true,
755 }
756 `
757 testcases := []struct {
758 name string
759 expectedHash string
760 }{
761 {
Colin Crossda6401b2021-04-21 11:32:19 -0700762 name: "hash0",
763 expectedHash: hashOf("implicit\nin1.txt\nin2.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800764 },
765 {
Colin Crossda6401b2021-04-21 11:32:19 -0700766 name: "hash1",
767 expectedHash: hashOf("implicit\nin1.txt\nin2.txt\nin3.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800768 },
769 }
770
Paul Duffin30ac3e72021-03-20 00:36:14 +0000771 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000772 prepareForRuleBuilderTest,
773 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000774 ).RunTest(t)
Colin Cross3d680512020-11-13 16:23:53 -0800775
776 for _, test := range testcases {
777 t.Run(test.name, func(t *testing.T) {
778 t.Run("sbox", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000779 gen := result.ModuleForTests(test.name+"_sbox", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800780 manifest := RuleBuilderSboxProtoForTests(t, gen.Output("sbox.textproto"))
781 hash := manifest.Commands[0].GetInputHash()
782
Paul Duffind250ff62021-03-16 21:51:29 +0000783 AssertStringEquals(t, "hash", test.expectedHash, hash)
Colin Cross3d680512020-11-13 16:23:53 -0800784 })
785 t.Run("", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000786 gen := result.ModuleForTests(test.name+"", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800787 command := gen.Output("gen/" + test.name).RuleParams.Command
Colin Cross3d680512020-11-13 16:23:53 -0800788 if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
789 t.Errorf("Expected command line to end with %q, got %q", w, g)
790 }
791 })
792 })
793 }
794}