blob: 24c8976a3de4d96f593b67316e5452e50a116ecf [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 Cross69f59a32019-02-15 10:39:37 -080067 // commands: "ld a.o b.o -o out/linked && echo success"
Colin Cross758290d2019-02-01 16:42:32 -080068 // tools: ["ld"]
69 // inputs: ["a.o" "b.o"]
Colin Cross69f59a32019-02-15 10:39:37 -080070 // outputs: ["out/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"))
82 rule.Command().Text("cp out/a out/b").
83 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:
92 // commands: "ln -s a.o out/a && cp out/a out/b"
93 // tools: ["ln"]
94 // inputs: ["a.o"]
95 // outputs: ["out/a" "out/b"]
96 // symlink_outputs: ["out/a" "out/b"]
97}
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 Cross69f59a32019-02-15 10:39:37 -0800120 // commands: "cp a out/b && cp out/b out/c"
Colin Cross5cb5b092019-02-02 21:25:18 -0800121 // tools: ["cp"]
122 // inputs: ["a"]
Colin Cross69f59a32019-02-15 10:39:37 -0800123 // outputs: ["out/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 Cross69f59a32019-02-15 10:39:37 -0800148 // commands: "cp a out/b && cp out/b out/c && rm -f out/b"
Colin Cross5cb5b092019-02-02 21:25:18 -0800149 // tools: ["cp"]
150 // inputs: ["a"]
Colin Cross69f59a32019-02-15 10:39:37 -0800151 // outputs: ["out/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 Cross69f59a32019-02-15 10:39:37 -0800171 // rule.Installs().String() = "out/linked:/bin/linked out/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 Cross70c47412021-03-12 17:48:14 -0800274 // javac @out/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 Crossab020a72021-03-12 17:52:23 -0800325 SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")).
326 ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700327 Text("Text").
328 Tool(PathForSource(ctx, "Tool"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800329
Dan Willemsen633c5022019-04-12 11:11:38 -0700330 rule.Command().
331 Text("command2").
Colin Crossab020a72021-03-12 17:52:23 -0800332 DepFile(PathForOutput(ctx, "module/depfile2")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700333 Input(PathForSource(ctx, "input2")).
Colin Crossab020a72021-03-12 17:52:23 -0800334 Output(PathForOutput(ctx, "module/output2")).
Colin Crossda71eda2020-02-21 16:55:19 -0800335 OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Dan Willemsen633c5022019-04-12 11:11:38 -0700336 Tool(PathForSource(ctx, "tool2"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800337
Dan Willemsen633c5022019-04-12 11:11:38 -0700338 // Test updates to the first command after the second command has been started
339 cmd.Text("after command2")
340 // Test updating a command when the previous update did not replace the cmd variable
341 cmd.Text("old cmd")
Colin Crossfeec25b2019-01-30 17:32:39 -0800342
Dan Willemsen633c5022019-04-12 11:11:38 -0700343 // Test a command that uses the output of a previous command as an input
344 rule.Command().
345 Text("command3").
346 Input(PathForSource(ctx, "input3")).
Colin Crossab020a72021-03-12 17:52:23 -0800347 Input(PathForOutput(ctx, "module/output2")).
348 Output(PathForOutput(ctx, "module/output3")).
349 Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
350 Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
Colin Crossfeec25b2019-01-30 17:32:39 -0800351 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700352
Colin Cross69f59a32019-02-15 10:39:37 -0800353 wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
Colin Crossab020a72021-03-12 17:52:23 -0800354 wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
355 PathForOutput(ctx, "other/RspOutput2")}
356 wantOutputs := PathsForOutput(ctx, []string{
357 "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput",
358 "module/output", "module/output2", "module/output3"})
359 wantDepFiles := PathsForOutput(ctx, []string{
360 "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
Colin Cross69f59a32019-02-15 10:39:37 -0800361 wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
Colin Crossda71eda2020-02-21 16:55:19 -0800362 wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
Colin Crossab020a72021-03-12 17:52:23 -0800363 wantSymlinkOutputs := PathsForOutput(ctx, []string{
364 "module/ImplicitSymlinkOutput", "module/SymlinkOutput"})
Colin Crossfeec25b2019-01-30 17:32:39 -0800365
Dan Willemsen633c5022019-04-12 11:11:38 -0700366 t.Run("normal", func(t *testing.T) {
Colin Crossf1a035e2020-11-16 17:32:30 -0800367 rule := NewRuleBuilder(pctx, ctx)
Dan Willemsen633c5022019-04-12 11:11:38 -0700368 addCommands(rule)
Colin Cross1d2cf042019-03-29 15:33:06 -0700369
Dan Willemsen633c5022019-04-12 11:11:38 -0700370 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800371 "out_local/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/module/depfile " +
372 "FlagWithInput=input FlagWithOutput=out_local/module/output FlagWithRspFileInputList=out_local/rsp " +
373 "Input out_local/module/Output out_local/module/SymlinkOutput Text Tool after command2 old cmd",
374 "command2 out_local/module/depfile2 input2 out_local/module/output2 tool2",
375 "command3 input3 out_local/module/output2 out_local/module/output3 input3 out_local/module/output2",
Dan Willemsen633c5022019-04-12 11:11:38 -0700376 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700377
Colin Crossab020a72021-03-12 17:52:23 -0800378 wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
379 "out_local/module/DepFile out_local/module/depfile out_local/module/ImplicitDepFile out_local/module/depfile2"
380
Paul Duffind250ff62021-03-16 21:51:29 +0000381 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700382
Paul Duffind250ff62021-03-16 21:51:29 +0000383 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800384 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000385 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
386 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
387 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
388 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
389 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Dan Willemsen633c5022019-04-12 11:11:38 -0700390
Paul Duffind250ff62021-03-16 21:51:29 +0000391 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700392 })
393
394 t.Run("sbox", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800395 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crosse16ce362020-11-12 08:29:30 -0800396 PathForOutput(ctx, "sbox.textproto"))
Dan Willemsen633c5022019-04-12 11:11:38 -0700397 addCommands(rule)
398
399 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800400 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
401 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
402 "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
403 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
Colin Crosse16ce362020-11-12 08:29:30 -0800404 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
Colin Crossab020a72021-03-12 17:52:23 -0800405 "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 -0700406 }
407
Colin Crossab020a72021-03-12 17:52:23 -0800408 wantDepMergerCommand := "out_local/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"
409
Paul Duffind250ff62021-03-16 21:51:29 +0000410 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700411
Paul Duffind250ff62021-03-16 21:51:29 +0000412 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800413 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000414 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800415 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000416 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
417 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
418 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Dan Willemsen633c5022019-04-12 11:11:38 -0700419
Paul Duffind250ff62021-03-16 21:51:29 +0000420 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700421 })
Colin Crossba9e4032020-11-24 16:32:22 -0800422
423 t.Run("sbox tools", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800424 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crossba9e4032020-11-24 16:32:22 -0800425 PathForOutput(ctx, "sbox.textproto")).SandboxTools()
426 addCommands(rule)
427
428 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800429 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
430 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
431 "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
432 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
Colin Crossba9e4032020-11-24 16:32:22 -0800433 "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 -0800434 "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 -0800435 }
436
437 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"
438
Paul Duffind250ff62021-03-16 21:51:29 +0000439 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Colin Crossba9e4032020-11-24 16:32:22 -0800440
Paul Duffind250ff62021-03-16 21:51:29 +0000441 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800442 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000443 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800444 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000445 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
446 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
447 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossba9e4032020-11-24 16:32:22 -0800448
Paul Duffind250ff62021-03-16 21:51:29 +0000449 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Colin Crossba9e4032020-11-24 16:32:22 -0800450 })
Colin Cross045bfd92021-03-24 16:38:03 -0700451
452 t.Run("sbox inputs", func(t *testing.T) {
453 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
454 PathForOutput(ctx, "sbox.textproto")).SandboxInputs()
455 addCommands(rule)
456
457 wantCommands := []string{
458 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
459 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
460 "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
461 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
462 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
463 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
464 }
465
466 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"
467
468 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
469
470 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
471 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
472 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
473 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
474 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
475 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
476 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
477
478 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
479 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800480}
481
482func testRuleBuilderFactory() Module {
483 module := &testRuleBuilderModule{}
484 module.AddProperties(&module.properties)
485 InitAndroidModule(module)
486 return module
487}
488
489type testRuleBuilderModule struct {
490 ModuleBase
491 properties struct {
Colin Cross3d680512020-11-13 16:23:53 -0800492 Srcs []string
Dan Willemsen633c5022019-04-12 11:11:38 -0700493
Colin Crossce3a51d2021-03-19 16:22:12 -0700494 Restat bool
495 Sbox bool
496 Sbox_inputs bool
Colin Crossfeec25b2019-01-30 17:32:39 -0800497 }
498}
499
500func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross3d680512020-11-13 16:23:53 -0800501 in := PathsForSource(ctx, t.properties.Srcs)
Colin Crossda6401b2021-04-21 11:32:19 -0700502 implicit := PathForSource(ctx, "implicit")
503 orderOnly := PathForSource(ctx, "orderonly")
Colin Crosse16ce362020-11-12 08:29:30 -0800504 out := PathForModuleOut(ctx, "gen", ctx.ModuleName())
505 outDep := PathForModuleOut(ctx, "gen", ctx.ModuleName()+".d")
506 outDir := PathForModuleOut(ctx, "gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700507 rspFile := PathForModuleOut(ctx, "rsp")
508 rspFile2 := PathForModuleOut(ctx, "rsp2")
509 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
510 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800511 manifestPath := PathForModuleOut(ctx, "sbox.textproto")
Colin Crossfeec25b2019-01-30 17:32:39 -0800512
Colin Crossda6401b2021-04-21 11:32:19 -0700513 testRuleBuilder_Build(ctx, in, implicit, orderOnly, out, outDep, outDir,
514 manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs,
515 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800516}
517
518type testRuleBuilderSingleton struct{}
519
520func testRuleBuilderSingletonFactory() Singleton {
521 return &testRuleBuilderSingleton{}
522}
523
524func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
Colin Crossda6401b2021-04-21 11:32:19 -0700525 in := PathsForSource(ctx, []string{"in"})
526 implicit := PathForSource(ctx, "implicit")
527 orderOnly := PathForSource(ctx, "orderonly")
Colin Crosse16ce362020-11-12 08:29:30 -0800528 out := PathForOutput(ctx, "singleton/gen/baz")
529 outDep := PathForOutput(ctx, "singleton/gen/baz.d")
530 outDir := PathForOutput(ctx, "singleton/gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700531 rspFile := PathForOutput(ctx, "singleton/rsp")
532 rspFile2 := PathForOutput(ctx, "singleton/rsp2")
533 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
534 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800535 manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
Colin Crossda6401b2021-04-21 11:32:19 -0700536
537 testRuleBuilder_Build(ctx, in, implicit, orderOnly, out, outDep, outDir,
538 manifestPath, true, false, false,
Colin Crossce3a51d2021-03-19 16:22:12 -0700539 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800540}
541
Colin Crossda6401b2021-04-21 11:32:19 -0700542func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly Path,
543 out, outDep, outDir, manifestPath WritablePath,
Colin Crossce3a51d2021-03-19 16:22:12 -0700544 restat, sbox, sboxInputs bool,
545 rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
546
Colin Crossf1a035e2020-11-16 17:32:30 -0800547 rule := NewRuleBuilder(pctx, ctx)
Colin Cross786cd6d2019-02-01 16:41:11 -0800548
Dan Willemsen633c5022019-04-12 11:11:38 -0700549 if sbox {
Colin Crosse16ce362020-11-12 08:29:30 -0800550 rule.Sbox(outDir, manifestPath)
Colin Crossce3a51d2021-03-19 16:22:12 -0700551 if sboxInputs {
552 rule.SandboxInputs()
553 }
Dan Willemsen633c5022019-04-12 11:11:38 -0700554 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800555
Colin Crossce3a51d2021-03-19 16:22:12 -0700556 rule.Command().
557 Tool(PathForSource(ctx, "cp")).
558 Inputs(in).
Colin Crossda6401b2021-04-21 11:32:19 -0700559 Implicit(implicit).
560 OrderOnly(orderOnly).
Colin Crossce3a51d2021-03-19 16:22:12 -0700561 Output(out).
562 ImplicitDepFile(outDep).
563 FlagWithRspFileInputList("@", rspFile, rspFileContents).
564 FlagWithRspFileInputList("@", rspFile2, rspFileContents2)
Dan Willemsen633c5022019-04-12 11:11:38 -0700565
566 if restat {
567 rule.Restat()
568 }
Colin Crossbaa676f2019-02-25 14:56:01 -0800569
Colin Crossf1a035e2020-11-16 17:32:30 -0800570 rule.Build("rule", "desc")
Colin Crossfeec25b2019-01-30 17:32:39 -0800571}
572
Paul Duffind250ff62021-03-16 21:51:29 +0000573var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
574 ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
575 ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
576})
577
Colin Crossfeec25b2019-01-30 17:32:39 -0800578func TestRuleBuilder_Build(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000579 fs := MockFS{
Colin Crossda6401b2021-04-21 11:32:19 -0700580 "in": nil,
581 "cp": nil,
Colin Cross98be1bb2019-12-13 20:41:13 -0800582 }
583
Colin Crossfeec25b2019-01-30 17:32:39 -0800584 bp := `
585 rule_builder_test {
586 name: "foo",
Colin Crossda6401b2021-04-21 11:32:19 -0700587 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700588 restat: true,
589 }
590 rule_builder_test {
591 name: "foo_sbox",
Colin Crossda6401b2021-04-21 11:32:19 -0700592 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700593 sbox: true,
Colin Crossfeec25b2019-01-30 17:32:39 -0800594 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700595 rule_builder_test {
596 name: "foo_sbox_inputs",
Colin Crossda6401b2021-04-21 11:32:19 -0700597 srcs: ["in"],
Colin Crossce3a51d2021-03-19 16:22:12 -0700598 sbox: true,
599 sbox_inputs: true,
600 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800601 `
602
Paul Duffin30ac3e72021-03-20 00:36:14 +0000603 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000604 prepareForRuleBuilderTest,
605 FixtureWithRootAndroidBp(bp),
606 fs.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000607 ).RunTest(t)
Colin Crossfeec25b2019-01-30 17:32:39 -0800608
Colin Crossce3a51d2021-03-19 16:22:12 -0700609 check := func(t *testing.T, params TestingBuildParams, rspFile2Params TestingBuildParams,
610 wantCommand, wantOutput, wantDepfile, wantRspFile, wantRspFile2 string,
611 wantRestat bool, extraImplicits, extraCmdDeps []string) {
612
Dan Willemsenc89b6f12019-08-29 14:47:40 -0700613 t.Helper()
Colin Cross3d680512020-11-13 16:23:53 -0800614 command := params.RuleParams.Command
Colin Crosse16ce362020-11-12 08:29:30 -0800615 re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
Colin Cross3d680512020-11-13 16:23:53 -0800616 command = re.ReplaceAllLiteralString(command, "")
Paul Duffind250ff62021-03-16 21:51:29 +0000617
618 AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
Dan Willemsen633c5022019-04-12 11:11:38 -0700619
620 wantDeps := append([]string{"cp"}, extraCmdDeps...)
Paul Duffind250ff62021-03-16 21:51:29 +0000621 AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
Dan Willemsen633c5022019-04-12 11:11:38 -0700622
Paul Duffind250ff62021-03-16 21:51:29 +0000623 AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
Colin Crossfeec25b2019-01-30 17:32:39 -0800624
Colin Crossce3a51d2021-03-19 16:22:12 -0700625 wantInputs := []string{"rsp_in"}
626 AssertArrayString(t, "Inputs", wantInputs, params.Inputs.Strings())
627
Colin Crossda6401b2021-04-21 11:32:19 -0700628 wantImplicits := append([]string{"implicit", "in"}, extraImplicits...)
Colin Crossce3a51d2021-03-19 16:22:12 -0700629 // The second rsp file and the files listed in it should be in implicits
630 wantImplicits = append(wantImplicits, "rsp_in2", wantRspFile2)
Paul Duffin709e0e32021-03-22 10:09:02 +0000631 AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
Colin Crossfeec25b2019-01-30 17:32:39 -0800632
Colin Crossda6401b2021-04-21 11:32:19 -0700633 wantOrderOnlys := []string{"orderonly"}
634 AssertPathsRelativeToTopEquals(t, "OrderOnly", wantOrderOnlys, params.OrderOnly)
635
Colin Crossce3a51d2021-03-19 16:22:12 -0700636 wantRspFileContent := "$in"
637 AssertStringEquals(t, "RspfileContent", wantRspFileContent, params.RuleParams.RspfileContent)
638
639 AssertStringEquals(t, "Rspfile", wantRspFile, params.RuleParams.Rspfile)
640
Paul Duffin709e0e32021-03-22 10:09:02 +0000641 AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
Colin Crossbaa676f2019-02-25 14:56:01 -0800642
Dan Willemsen633c5022019-04-12 11:11:38 -0700643 if len(params.ImplicitOutputs) != 0 {
644 t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
645 }
646
Paul Duffin709e0e32021-03-22 10:09:02 +0000647 AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
Dan Willemsen633c5022019-04-12 11:11:38 -0700648
649 if params.Deps != blueprint.DepsGCC {
650 t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
Colin Crossbaa676f2019-02-25 14:56:01 -0800651 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700652
653 rspFile2Content := ContentFromFileRuleForTests(t, rspFile2Params)
654 AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
Colin Crossfeec25b2019-01-30 17:32:39 -0800655 }
656
Colin Cross4c83e5c2019-02-25 14:54:28 -0800657 t.Run("module", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000658 outFile := "out/soong/.intermediates/foo/gen/foo"
Colin Crossce3a51d2021-03-19 16:22:12 -0700659 rspFile := "out/soong/.intermediates/foo/rsp"
660 rspFile2 := "out/soong/.intermediates/foo/rsp2"
661 module := result.ModuleForTests("foo", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100662 check(t, module.Rule("rule"), module.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700663 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700664 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Dan Willemsen633c5022019-04-12 11:11:38 -0700665 })
666 t.Run("sbox", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000667 outDir := "out/soong/.intermediates/foo_sbox"
Colin Crosse16ce362020-11-12 08:29:30 -0800668 outFile := filepath.Join(outDir, "gen/foo_sbox")
669 depFile := filepath.Join(outDir, "gen/foo_sbox.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700670 rspFile := filepath.Join(outDir, "rsp")
671 rspFile2 := filepath.Join(outDir, "rsp2")
672 manifest := filepath.Join(outDir, "sbox.textproto")
673 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
674 sandboxPath := shared.TempDirForOutDir("out/soong")
675
676 cmd := `rm -rf ` + outDir + `/gen && ` +
677 sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
678 module := result.ModuleForTests("foo_sbox", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100679 check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700680 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
681 })
682 t.Run("sbox_inputs", func(t *testing.T) {
683 outDir := "out/soong/.intermediates/foo_sbox_inputs"
684 outFile := filepath.Join(outDir, "gen/foo_sbox_inputs")
685 depFile := filepath.Join(outDir, "gen/foo_sbox_inputs.d")
686 rspFile := filepath.Join(outDir, "rsp")
687 rspFile2 := filepath.Join(outDir, "rsp2")
Colin Crosse16ce362020-11-12 08:29:30 -0800688 manifest := filepath.Join(outDir, "sbox.textproto")
Paul Duffin709e0e32021-03-22 10:09:02 +0000689 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
690 sandboxPath := shared.TempDirForOutDir("out/soong")
Dan Willemsen633c5022019-04-12 11:11:38 -0700691
Colin Crosse16ce362020-11-12 08:29:30 -0800692 cmd := `rm -rf ` + outDir + `/gen && ` +
693 sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
Dan Willemsen633c5022019-04-12 11:11:38 -0700694
Colin Crossce3a51d2021-03-19 16:22:12 -0700695 module := result.ModuleForTests("foo_sbox_inputs", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100696 check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700697 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
Colin Cross4c83e5c2019-02-25 14:54:28 -0800698 })
699 t.Run("singleton", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000700 outFile := filepath.Join("out/soong/singleton/gen/baz")
Colin Crossce3a51d2021-03-19 16:22:12 -0700701 rspFile := filepath.Join("out/soong/singleton/rsp")
702 rspFile2 := filepath.Join("out/soong/singleton/rsp2")
703 singleton := result.SingletonForTests("rule_builder_test")
Paul Duffina71a67a2021-03-29 00:42:57 +0100704 check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700705 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700706 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Colin Cross4c83e5c2019-02-25 14:54:28 -0800707 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800708}
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700709
Colin Cross3d680512020-11-13 16:23:53 -0800710func TestRuleBuilderHashInputs(t *testing.T) {
711 // The basic idea here is to verify that the command (in the case of a
712 // non-sbox rule) or the sbox textproto manifest contain a hash of the
713 // inputs.
714
715 // By including a hash of the inputs, we cause the rule to re-run if
716 // the list of inputs changes because the command line or a dependency
717 // changes.
718
Colin Crossda6401b2021-04-21 11:32:19 -0700719 hashOf := func(s string) string {
720 sum := sha256.Sum256([]byte(s))
721 return hex.EncodeToString(sum[:])
722 }
723
Colin Cross3d680512020-11-13 16:23:53 -0800724 bp := `
725 rule_builder_test {
726 name: "hash0",
727 srcs: ["in1.txt", "in2.txt"],
728 }
729 rule_builder_test {
730 name: "hash0_sbox",
731 srcs: ["in1.txt", "in2.txt"],
732 sbox: true,
733 }
734 rule_builder_test {
735 name: "hash1",
736 srcs: ["in1.txt", "in2.txt", "in3.txt"],
737 }
738 rule_builder_test {
739 name: "hash1_sbox",
740 srcs: ["in1.txt", "in2.txt", "in3.txt"],
741 sbox: true,
742 }
743 `
744 testcases := []struct {
745 name string
746 expectedHash string
747 }{
748 {
Colin Crossda6401b2021-04-21 11:32:19 -0700749 name: "hash0",
750 expectedHash: hashOf("implicit\nin1.txt\nin2.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800751 },
752 {
Colin Crossda6401b2021-04-21 11:32:19 -0700753 name: "hash1",
754 expectedHash: hashOf("implicit\nin1.txt\nin2.txt\nin3.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800755 },
756 }
757
Paul Duffin30ac3e72021-03-20 00:36:14 +0000758 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000759 prepareForRuleBuilderTest,
760 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000761 ).RunTest(t)
Colin Cross3d680512020-11-13 16:23:53 -0800762
763 for _, test := range testcases {
764 t.Run(test.name, func(t *testing.T) {
765 t.Run("sbox", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000766 gen := result.ModuleForTests(test.name+"_sbox", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800767 manifest := RuleBuilderSboxProtoForTests(t, gen.Output("sbox.textproto"))
768 hash := manifest.Commands[0].GetInputHash()
769
Paul Duffind250ff62021-03-16 21:51:29 +0000770 AssertStringEquals(t, "hash", test.expectedHash, hash)
Colin Cross3d680512020-11-13 16:23:53 -0800771 })
772 t.Run("", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000773 gen := result.ModuleForTests(test.name+"", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800774 command := gen.Output("gen/" + test.name).RuleParams.Command
Colin Cross3d680512020-11-13 16:23:53 -0800775 if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
776 t.Errorf("Expected command line to end with %q, got %q", w, g)
777 }
778 })
779 })
780 }
781}