blob: 9c5ca41486b2c80752c5174d568112c95f113aab [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 Cross758290d2019-02-01 16:42:32 -080018 "fmt"
Colin Crossfeec25b2019-01-30 17:32:39 -080019 "path/filepath"
Colin Cross3d680512020-11-13 16:23:53 -080020 "regexp"
Colin Cross758290d2019-02-01 16:42:32 -080021 "strings"
Colin Crossfeec25b2019-01-30 17:32:39 -080022 "testing"
Dan Willemsen633c5022019-04-12 11:11:38 -070023
24 "github.com/google/blueprint"
25
26 "android/soong/shared"
Colin Crossfeec25b2019-01-30 17:32:39 -080027)
28
Colin Crossf1a035e2020-11-16 17:32:30 -080029func builderContext() BuilderContext {
30 return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
Colin Cross98be1bb2019-12-13 20:41:13 -080031 "ld": nil,
32 "a.o": nil,
33 "b.o": nil,
34 "cp": nil,
35 "a": nil,
36 "b": nil,
37 "ls": nil,
Jingwen Chence679d22020-09-23 04:30:02 +000038 "ln": nil,
Colin Cross98be1bb2019-12-13 20:41:13 -080039 "turbine": nil,
40 "java": nil,
41 "javac": nil,
42 }))
Colin Cross69f59a32019-02-15 10:39:37 -080043}
44
Colin Cross758290d2019-02-01 16:42:32 -080045func ExampleRuleBuilder() {
Colin Crossf1a035e2020-11-16 17:32:30 -080046 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -080047
Colin Crossf1a035e2020-11-16 17:32:30 -080048 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -080049
50 rule.Command().
51 Tool(PathForSource(ctx, "ld")).
52 Inputs(PathsForTesting("a.o", "b.o")).
53 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -080054 rule.Command().Text("echo success")
55
56 // To add the command to the build graph:
Colin Crossf1a035e2020-11-16 17:32:30 -080057 // rule.Build("link", "link")
Colin Cross758290d2019-02-01 16:42:32 -080058
59 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
60 fmt.Printf("tools: %q\n", rule.Tools())
61 fmt.Printf("inputs: %q\n", rule.Inputs())
62 fmt.Printf("outputs: %q\n", rule.Outputs())
63
64 // Output:
Colin Cross69f59a32019-02-15 10:39:37 -080065 // commands: "ld a.o b.o -o out/linked && echo success"
Colin Cross758290d2019-02-01 16:42:32 -080066 // tools: ["ld"]
67 // inputs: ["a.o" "b.o"]
Colin Cross69f59a32019-02-15 10:39:37 -080068 // outputs: ["out/linked"]
Colin Cross758290d2019-02-01 16:42:32 -080069}
70
Jingwen Chence679d22020-09-23 04:30:02 +000071func ExampleRuleBuilder_SymlinkOutputs() {
Colin Crossf1a035e2020-11-16 17:32:30 -080072 ctx := builderContext()
Jingwen Chence679d22020-09-23 04:30:02 +000073
Colin Crossf1a035e2020-11-16 17:32:30 -080074 rule := NewRuleBuilder(pctx, ctx)
Jingwen Chence679d22020-09-23 04:30:02 +000075
76 rule.Command().
77 Tool(PathForSource(ctx, "ln")).
78 FlagWithInput("-s ", PathForTesting("a.o")).
79 SymlinkOutput(PathForOutput(ctx, "a"))
80 rule.Command().Text("cp out/a out/b").
81 ImplicitSymlinkOutput(PathForOutput(ctx, "b"))
82
83 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
84 fmt.Printf("tools: %q\n", rule.Tools())
85 fmt.Printf("inputs: %q\n", rule.Inputs())
86 fmt.Printf("outputs: %q\n", rule.Outputs())
87 fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs())
88
89 // Output:
90 // commands: "ln -s a.o out/a && cp out/a out/b"
91 // tools: ["ln"]
92 // inputs: ["a.o"]
93 // outputs: ["out/a" "out/b"]
94 // symlink_outputs: ["out/a" "out/b"]
95}
96
Colin Cross5cb5b092019-02-02 21:25:18 -080097func ExampleRuleBuilder_Temporary() {
Colin Crossf1a035e2020-11-16 17:32:30 -080098 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -080099
Colin Crossf1a035e2020-11-16 17:32:30 -0800100 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800101
102 rule.Command().
103 Tool(PathForSource(ctx, "cp")).
104 Input(PathForSource(ctx, "a")).
105 Output(PathForOutput(ctx, "b"))
106 rule.Command().
107 Tool(PathForSource(ctx, "cp")).
108 Input(PathForOutput(ctx, "b")).
109 Output(PathForOutput(ctx, "c"))
110 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -0800111
112 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
113 fmt.Printf("tools: %q\n", rule.Tools())
114 fmt.Printf("inputs: %q\n", rule.Inputs())
115 fmt.Printf("outputs: %q\n", rule.Outputs())
116
117 // Output:
Colin Cross69f59a32019-02-15 10:39:37 -0800118 // commands: "cp a out/b && cp out/b out/c"
Colin Cross5cb5b092019-02-02 21:25:18 -0800119 // tools: ["cp"]
120 // inputs: ["a"]
Colin Cross69f59a32019-02-15 10:39:37 -0800121 // outputs: ["out/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800122}
123
124func ExampleRuleBuilder_DeleteTemporaryFiles() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800125 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -0800126
Colin Crossf1a035e2020-11-16 17:32:30 -0800127 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800128
129 rule.Command().
130 Tool(PathForSource(ctx, "cp")).
131 Input(PathForSource(ctx, "a")).
132 Output(PathForOutput(ctx, "b"))
133 rule.Command().
134 Tool(PathForSource(ctx, "cp")).
135 Input(PathForOutput(ctx, "b")).
136 Output(PathForOutput(ctx, "c"))
137 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -0800138 rule.DeleteTemporaryFiles()
139
140 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
141 fmt.Printf("tools: %q\n", rule.Tools())
142 fmt.Printf("inputs: %q\n", rule.Inputs())
143 fmt.Printf("outputs: %q\n", rule.Outputs())
144
145 // Output:
Colin Cross69f59a32019-02-15 10:39:37 -0800146 // commands: "cp a out/b && cp out/b out/c && rm -f out/b"
Colin Cross5cb5b092019-02-02 21:25:18 -0800147 // tools: ["cp"]
148 // inputs: ["a"]
Colin Cross69f59a32019-02-15 10:39:37 -0800149 // outputs: ["out/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800150}
151
Colin Crossdeabb942019-02-11 14:11:09 -0800152func ExampleRuleBuilder_Installs() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800153 ctx := builderContext()
Colin Crossdeabb942019-02-11 14:11:09 -0800154
Colin Crossf1a035e2020-11-16 17:32:30 -0800155 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800156
157 out := PathForOutput(ctx, "linked")
158
159 rule.Command().
160 Tool(PathForSource(ctx, "ld")).
161 Inputs(PathsForTesting("a.o", "b.o")).
162 FlagWithOutput("-o ", out)
163 rule.Install(out, "/bin/linked")
164 rule.Install(out, "/sbin/linked")
Colin Crossdeabb942019-02-11 14:11:09 -0800165
166 fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
167
168 // Output:
Colin Cross69f59a32019-02-15 10:39:37 -0800169 // rule.Installs().String() = "out/linked:/bin/linked out/linked:/sbin/linked"
Colin Crossdeabb942019-02-11 14:11:09 -0800170}
171
Colin Cross758290d2019-02-01 16:42:32 -0800172func ExampleRuleBuilderCommand() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800173 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -0800174
Colin Crossf1a035e2020-11-16 17:32:30 -0800175 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800176
Colin Cross758290d2019-02-01 16:42:32 -0800177 // chained
Colin Cross69f59a32019-02-15 10:39:37 -0800178 rule.Command().
179 Tool(PathForSource(ctx, "ld")).
180 Inputs(PathsForTesting("a.o", "b.o")).
181 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800182
183 // unchained
184 cmd := rule.Command()
Colin Cross69f59a32019-02-15 10:39:37 -0800185 cmd.Tool(PathForSource(ctx, "ld"))
186 cmd.Inputs(PathsForTesting("a.o", "b.o"))
187 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800188
189 // mixed:
Colin Cross69f59a32019-02-15 10:39:37 -0800190 cmd = rule.Command().Tool(PathForSource(ctx, "ld"))
191 cmd.Inputs(PathsForTesting("a.o", "b.o"))
192 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800193}
194
195func ExampleRuleBuilderCommand_Flag() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800196 ctx := builderContext()
197 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800198 Tool(PathForSource(ctx, "ls")).Flag("-l"))
Colin Cross758290d2019-02-01 16:42:32 -0800199 // Output:
200 // ls -l
201}
202
Colin Cross92b7d582019-03-29 15:32:51 -0700203func ExampleRuleBuilderCommand_Flags() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800204 ctx := builderContext()
205 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross92b7d582019-03-29 15:32:51 -0700206 Tool(PathForSource(ctx, "ls")).Flags([]string{"-l", "-a"}))
207 // Output:
208 // ls -l -a
209}
210
Colin Cross758290d2019-02-01 16:42:32 -0800211func ExampleRuleBuilderCommand_FlagWithArg() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800212 ctx := builderContext()
213 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800214 Tool(PathForSource(ctx, "ls")).
Colin Cross758290d2019-02-01 16:42:32 -0800215 FlagWithArg("--sort=", "time"))
216 // Output:
217 // ls --sort=time
218}
219
Colin Crossc7ed0042019-02-11 14:11:09 -0800220func ExampleRuleBuilderCommand_FlagForEachArg() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800221 ctx := builderContext()
222 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800223 Tool(PathForSource(ctx, "ls")).
Colin Crossc7ed0042019-02-11 14:11:09 -0800224 FlagForEachArg("--sort=", []string{"time", "size"}))
225 // Output:
226 // ls --sort=time --sort=size
227}
228
Colin Cross758290d2019-02-01 16:42:32 -0800229func ExampleRuleBuilderCommand_FlagForEachInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800230 ctx := builderContext()
231 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800232 Tool(PathForSource(ctx, "turbine")).
233 FlagForEachInput("--classpath ", PathsForTesting("a.jar", "b.jar")))
Colin Cross758290d2019-02-01 16:42:32 -0800234 // Output:
235 // turbine --classpath a.jar --classpath b.jar
236}
237
238func ExampleRuleBuilderCommand_FlagWithInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800239 ctx := builderContext()
240 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800241 Tool(PathForSource(ctx, "java")).
242 FlagWithInputList("-classpath=", PathsForTesting("a.jar", "b.jar"), ":"))
Colin Cross758290d2019-02-01 16:42:32 -0800243 // Output:
244 // java -classpath=a.jar:b.jar
245}
246
247func ExampleRuleBuilderCommand_FlagWithInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800248 ctx := builderContext()
249 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800250 Tool(PathForSource(ctx, "java")).
251 FlagWithInput("-classpath=", PathForSource(ctx, "a")))
Colin Cross758290d2019-02-01 16:42:32 -0800252 // Output:
253 // java -classpath=a
254}
255
256func ExampleRuleBuilderCommand_FlagWithList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800257 ctx := builderContext()
258 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800259 Tool(PathForSource(ctx, "ls")).
Colin Cross758290d2019-02-01 16:42:32 -0800260 FlagWithList("--sort=", []string{"time", "size"}, ","))
261 // Output:
262 // ls --sort=time,size
263}
264
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700265func ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800266 ctx := builderContext()
267 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700268 Tool(PathForSource(ctx, "javac")).
Colin Cross70c47412021-03-12 17:48:14 -0800269 FlagWithRspFileInputList("@", PathForOutput(ctx, "foo.rsp"), PathsForTesting("a.java", "b.java")).
270 String())
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700271 // Output:
Colin Cross70c47412021-03-12 17:48:14 -0800272 // javac @out/foo.rsp
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700273}
274
275func ExampleRuleBuilderCommand_String() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800276 ctx := builderContext()
277 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700278 Text("FOO=foo").
279 Text("echo $FOO").
280 String())
281 // Output:
282 // FOO=foo echo $FOO
283}
284
Colin Crossfeec25b2019-01-30 17:32:39 -0800285func TestRuleBuilder(t *testing.T) {
Colin Cross69f59a32019-02-15 10:39:37 -0800286 fs := map[string][]byte{
Colin Crossda71eda2020-02-21 16:55:19 -0800287 "dep_fixer": nil,
288 "input": nil,
289 "Implicit": nil,
290 "Input": nil,
291 "OrderOnly": nil,
292 "OrderOnlys": nil,
293 "Tool": nil,
294 "input2": nil,
295 "tool2": nil,
296 "input3": nil,
Colin Cross69f59a32019-02-15 10:39:37 -0800297 }
298
Colin Crossab020a72021-03-12 17:52:23 -0800299 pathCtx := PathContextForTesting(TestConfig("out_local", nil, "", fs))
Colin Crossf1a035e2020-11-16 17:32:30 -0800300 ctx := builderContextForTests{
301 PathContext: pathCtx,
302 }
Colin Cross69f59a32019-02-15 10:39:37 -0800303
Dan Willemsen633c5022019-04-12 11:11:38 -0700304 addCommands := func(rule *RuleBuilder) {
305 cmd := rule.Command().
Colin Crossab020a72021-03-12 17:52:23 -0800306 DepFile(PathForOutput(ctx, "module/DepFile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700307 Flag("Flag").
308 FlagWithArg("FlagWithArg=", "arg").
Colin Crossab020a72021-03-12 17:52:23 -0800309 FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "module/depfile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700310 FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
Colin Crossab020a72021-03-12 17:52:23 -0800311 FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "module/output")).
312 FlagWithRspFileInputList("FlagWithRspFileInputList=", PathForOutput(ctx, "rsp"),
313 Paths{
314 PathForSource(ctx, "RspInput"),
315 PathForOutput(ctx, "other/RspOutput2"),
316 }).
Dan Willemsen633c5022019-04-12 11:11:38 -0700317 Implicit(PathForSource(ctx, "Implicit")).
Colin Crossab020a72021-03-12 17:52:23 -0800318 ImplicitDepFile(PathForOutput(ctx, "module/ImplicitDepFile")).
319 ImplicitOutput(PathForOutput(ctx, "module/ImplicitOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700320 Input(PathForSource(ctx, "Input")).
Colin Crossab020a72021-03-12 17:52:23 -0800321 Output(PathForOutput(ctx, "module/Output")).
Colin Crossda71eda2020-02-21 16:55:19 -0800322 OrderOnly(PathForSource(ctx, "OrderOnly")).
Colin Crossab020a72021-03-12 17:52:23 -0800323 SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")).
324 ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700325 Text("Text").
326 Tool(PathForSource(ctx, "Tool"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800327
Dan Willemsen633c5022019-04-12 11:11:38 -0700328 rule.Command().
329 Text("command2").
Colin Crossab020a72021-03-12 17:52:23 -0800330 DepFile(PathForOutput(ctx, "module/depfile2")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700331 Input(PathForSource(ctx, "input2")).
Colin Crossab020a72021-03-12 17:52:23 -0800332 Output(PathForOutput(ctx, "module/output2")).
Colin Crossda71eda2020-02-21 16:55:19 -0800333 OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Dan Willemsen633c5022019-04-12 11:11:38 -0700334 Tool(PathForSource(ctx, "tool2"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800335
Dan Willemsen633c5022019-04-12 11:11:38 -0700336 // Test updates to the first command after the second command has been started
337 cmd.Text("after command2")
338 // Test updating a command when the previous update did not replace the cmd variable
339 cmd.Text("old cmd")
Colin Crossfeec25b2019-01-30 17:32:39 -0800340
Dan Willemsen633c5022019-04-12 11:11:38 -0700341 // Test a command that uses the output of a previous command as an input
342 rule.Command().
343 Text("command3").
344 Input(PathForSource(ctx, "input3")).
Colin Crossab020a72021-03-12 17:52:23 -0800345 Input(PathForOutput(ctx, "module/output2")).
346 Output(PathForOutput(ctx, "module/output3")).
347 Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
348 Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
Colin Crossfeec25b2019-01-30 17:32:39 -0800349 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700350
Colin Cross69f59a32019-02-15 10:39:37 -0800351 wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
Colin Crossab020a72021-03-12 17:52:23 -0800352 wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
353 PathForOutput(ctx, "other/RspOutput2")}
354 wantOutputs := PathsForOutput(ctx, []string{
355 "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput",
356 "module/output", "module/output2", "module/output3"})
357 wantDepFiles := PathsForOutput(ctx, []string{
358 "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
Colin Cross69f59a32019-02-15 10:39:37 -0800359 wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
Colin Crossda71eda2020-02-21 16:55:19 -0800360 wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
Colin Crossab020a72021-03-12 17:52:23 -0800361 wantSymlinkOutputs := PathsForOutput(ctx, []string{
362 "module/ImplicitSymlinkOutput", "module/SymlinkOutput"})
Colin Crossfeec25b2019-01-30 17:32:39 -0800363
Dan Willemsen633c5022019-04-12 11:11:38 -0700364 t.Run("normal", func(t *testing.T) {
Colin Crossf1a035e2020-11-16 17:32:30 -0800365 rule := NewRuleBuilder(pctx, ctx)
Dan Willemsen633c5022019-04-12 11:11:38 -0700366 addCommands(rule)
Colin Cross1d2cf042019-03-29 15:33:06 -0700367
Dan Willemsen633c5022019-04-12 11:11:38 -0700368 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800369 "out_local/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/module/depfile " +
370 "FlagWithInput=input FlagWithOutput=out_local/module/output FlagWithRspFileInputList=out_local/rsp " +
371 "Input out_local/module/Output out_local/module/SymlinkOutput Text Tool after command2 old cmd",
372 "command2 out_local/module/depfile2 input2 out_local/module/output2 tool2",
373 "command3 input3 out_local/module/output2 out_local/module/output3 input3 out_local/module/output2",
Dan Willemsen633c5022019-04-12 11:11:38 -0700374 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700375
Colin Crossab020a72021-03-12 17:52:23 -0800376 wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
377 "out_local/module/DepFile out_local/module/depfile out_local/module/ImplicitDepFile out_local/module/depfile2"
378
Paul Duffind250ff62021-03-16 21:51:29 +0000379 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700380
Paul Duffind250ff62021-03-16 21:51:29 +0000381 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800382 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000383 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
384 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
385 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
386 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
387 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Dan Willemsen633c5022019-04-12 11:11:38 -0700388
Paul Duffind250ff62021-03-16 21:51:29 +0000389 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700390 })
391
392 t.Run("sbox", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800393 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crosse16ce362020-11-12 08:29:30 -0800394 PathForOutput(ctx, "sbox.textproto"))
Dan Willemsen633c5022019-04-12 11:11:38 -0700395 addCommands(rule)
396
397 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800398 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
399 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
400 "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
401 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
Colin Crosse16ce362020-11-12 08:29:30 -0800402 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
Colin Crossab020a72021-03-12 17:52:23 -0800403 "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 -0700404 }
405
Colin Crossab020a72021-03-12 17:52:23 -0800406 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"
407
Paul Duffind250ff62021-03-16 21:51:29 +0000408 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700409
Paul Duffind250ff62021-03-16 21:51:29 +0000410 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800411 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000412 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800413 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000414 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
415 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
416 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Dan Willemsen633c5022019-04-12 11:11:38 -0700417
Paul Duffind250ff62021-03-16 21:51:29 +0000418 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700419 })
Colin Crossba9e4032020-11-24 16:32:22 -0800420
421 t.Run("sbox tools", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800422 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crossba9e4032020-11-24 16:32:22 -0800423 PathForOutput(ctx, "sbox.textproto")).SandboxTools()
424 addCommands(rule)
425
426 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800427 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
428 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
429 "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
430 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
Colin Crossba9e4032020-11-24 16:32:22 -0800431 "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 -0800432 "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 -0800433 }
434
435 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"
436
Paul Duffind250ff62021-03-16 21:51:29 +0000437 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Colin Crossba9e4032020-11-24 16:32:22 -0800438
Paul Duffind250ff62021-03-16 21:51:29 +0000439 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800440 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000441 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Crossab020a72021-03-12 17:52:23 -0800442 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000443 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
444 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
445 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossba9e4032020-11-24 16:32:22 -0800446
Paul Duffind250ff62021-03-16 21:51:29 +0000447 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Colin Crossba9e4032020-11-24 16:32:22 -0800448 })
Colin Cross045bfd92021-03-24 16:38:03 -0700449
450 t.Run("sbox inputs", func(t *testing.T) {
451 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
452 PathForOutput(ctx, "sbox.textproto")).SandboxInputs()
453 addCommands(rule)
454
455 wantCommands := []string{
456 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
457 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
458 "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
459 "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
460 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
461 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
462 }
463
464 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"
465
466 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
467
468 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
469 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
470 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
471 AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
472 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
473 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
474 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
475
476 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
477 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800478}
479
480func testRuleBuilderFactory() Module {
481 module := &testRuleBuilderModule{}
482 module.AddProperties(&module.properties)
483 InitAndroidModule(module)
484 return module
485}
486
487type testRuleBuilderModule struct {
488 ModuleBase
489 properties struct {
Colin Cross3d680512020-11-13 16:23:53 -0800490 Srcs []string
Dan Willemsen633c5022019-04-12 11:11:38 -0700491
Colin Crossce3a51d2021-03-19 16:22:12 -0700492 Restat bool
493 Sbox bool
494 Sbox_inputs bool
Colin Crossfeec25b2019-01-30 17:32:39 -0800495 }
496}
497
498func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross3d680512020-11-13 16:23:53 -0800499 in := PathsForSource(ctx, t.properties.Srcs)
Colin Crosse16ce362020-11-12 08:29:30 -0800500 out := PathForModuleOut(ctx, "gen", ctx.ModuleName())
501 outDep := PathForModuleOut(ctx, "gen", ctx.ModuleName()+".d")
502 outDir := PathForModuleOut(ctx, "gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700503 rspFile := PathForModuleOut(ctx, "rsp")
504 rspFile2 := PathForModuleOut(ctx, "rsp2")
505 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
506 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800507 manifestPath := PathForModuleOut(ctx, "sbox.textproto")
Colin Crossfeec25b2019-01-30 17:32:39 -0800508
Colin Crossce3a51d2021-03-19 16:22:12 -0700509 testRuleBuilder_Build(ctx, in, out, outDep, outDir, manifestPath, t.properties.Restat,
510 t.properties.Sbox, t.properties.Sbox_inputs, rspFile, rspFileContents,
511 rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800512}
513
514type testRuleBuilderSingleton struct{}
515
516func testRuleBuilderSingletonFactory() Singleton {
517 return &testRuleBuilderSingleton{}
518}
519
520func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
521 in := PathForSource(ctx, "bar")
Colin Crosse16ce362020-11-12 08:29:30 -0800522 out := PathForOutput(ctx, "singleton/gen/baz")
523 outDep := PathForOutput(ctx, "singleton/gen/baz.d")
524 outDir := PathForOutput(ctx, "singleton/gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700525 rspFile := PathForOutput(ctx, "singleton/rsp")
526 rspFile2 := PathForOutput(ctx, "singleton/rsp2")
527 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
528 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800529 manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
Colin Crossce3a51d2021-03-19 16:22:12 -0700530 testRuleBuilder_Build(ctx, Paths{in}, out, outDep, outDir, manifestPath, true, false, false,
531 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800532}
533
Colin Crossce3a51d2021-03-19 16:22:12 -0700534func testRuleBuilder_Build(ctx BuilderContext, in Paths, out, outDep, outDir, manifestPath WritablePath,
535 restat, sbox, sboxInputs bool,
536 rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
537
Colin Crossf1a035e2020-11-16 17:32:30 -0800538 rule := NewRuleBuilder(pctx, ctx)
Colin Cross786cd6d2019-02-01 16:41:11 -0800539
Dan Willemsen633c5022019-04-12 11:11:38 -0700540 if sbox {
Colin Crosse16ce362020-11-12 08:29:30 -0800541 rule.Sbox(outDir, manifestPath)
Colin Crossce3a51d2021-03-19 16:22:12 -0700542 if sboxInputs {
543 rule.SandboxInputs()
544 }
Dan Willemsen633c5022019-04-12 11:11:38 -0700545 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800546
Colin Crossce3a51d2021-03-19 16:22:12 -0700547 rule.Command().
548 Tool(PathForSource(ctx, "cp")).
549 Inputs(in).
550 Output(out).
551 ImplicitDepFile(outDep).
552 FlagWithRspFileInputList("@", rspFile, rspFileContents).
553 FlagWithRspFileInputList("@", rspFile2, rspFileContents2)
Dan Willemsen633c5022019-04-12 11:11:38 -0700554
555 if restat {
556 rule.Restat()
557 }
Colin Crossbaa676f2019-02-25 14:56:01 -0800558
Colin Crossf1a035e2020-11-16 17:32:30 -0800559 rule.Build("rule", "desc")
Colin Crossfeec25b2019-01-30 17:32:39 -0800560}
561
Paul Duffind250ff62021-03-16 21:51:29 +0000562var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
563 ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
564 ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
565})
566
Colin Crossfeec25b2019-01-30 17:32:39 -0800567func TestRuleBuilder_Build(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000568 fs := MockFS{
Colin Cross98be1bb2019-12-13 20:41:13 -0800569 "bar": nil,
570 "cp": nil,
571 }
572
Colin Crossfeec25b2019-01-30 17:32:39 -0800573 bp := `
574 rule_builder_test {
575 name: "foo",
Colin Cross3d680512020-11-13 16:23:53 -0800576 srcs: ["bar"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700577 restat: true,
578 }
579 rule_builder_test {
580 name: "foo_sbox",
Colin Cross3d680512020-11-13 16:23:53 -0800581 srcs: ["bar"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700582 sbox: true,
Colin Crossfeec25b2019-01-30 17:32:39 -0800583 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700584 rule_builder_test {
585 name: "foo_sbox_inputs",
586 srcs: ["bar"],
587 sbox: true,
588 sbox_inputs: true,
589 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800590 `
591
Paul Duffin30ac3e72021-03-20 00:36:14 +0000592 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000593 prepareForRuleBuilderTest,
594 FixtureWithRootAndroidBp(bp),
595 fs.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000596 ).RunTest(t)
Colin Crossfeec25b2019-01-30 17:32:39 -0800597
Colin Crossce3a51d2021-03-19 16:22:12 -0700598 check := func(t *testing.T, params TestingBuildParams, rspFile2Params TestingBuildParams,
599 wantCommand, wantOutput, wantDepfile, wantRspFile, wantRspFile2 string,
600 wantRestat bool, extraImplicits, extraCmdDeps []string) {
601
Dan Willemsenc89b6f12019-08-29 14:47:40 -0700602 t.Helper()
Colin Cross3d680512020-11-13 16:23:53 -0800603 command := params.RuleParams.Command
Colin Crosse16ce362020-11-12 08:29:30 -0800604 re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
Colin Cross3d680512020-11-13 16:23:53 -0800605 command = re.ReplaceAllLiteralString(command, "")
Paul Duffind250ff62021-03-16 21:51:29 +0000606
607 AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
Dan Willemsen633c5022019-04-12 11:11:38 -0700608
609 wantDeps := append([]string{"cp"}, extraCmdDeps...)
Paul Duffind250ff62021-03-16 21:51:29 +0000610 AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
Dan Willemsen633c5022019-04-12 11:11:38 -0700611
Paul Duffind250ff62021-03-16 21:51:29 +0000612 AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
Colin Crossfeec25b2019-01-30 17:32:39 -0800613
Colin Crossce3a51d2021-03-19 16:22:12 -0700614 wantInputs := []string{"rsp_in"}
615 AssertArrayString(t, "Inputs", wantInputs, params.Inputs.Strings())
616
Colin Crosse16ce362020-11-12 08:29:30 -0800617 wantImplicits := append([]string{"bar"}, extraImplicits...)
Colin Crossce3a51d2021-03-19 16:22:12 -0700618 // The second rsp file and the files listed in it should be in implicits
619 wantImplicits = append(wantImplicits, "rsp_in2", wantRspFile2)
Paul Duffin709e0e32021-03-22 10:09:02 +0000620 AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
Colin Crossfeec25b2019-01-30 17:32:39 -0800621
Colin Crossce3a51d2021-03-19 16:22:12 -0700622 wantRspFileContent := "$in"
623 AssertStringEquals(t, "RspfileContent", wantRspFileContent, params.RuleParams.RspfileContent)
624
625 AssertStringEquals(t, "Rspfile", wantRspFile, params.RuleParams.Rspfile)
626
Paul Duffin709e0e32021-03-22 10:09:02 +0000627 AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
Colin Crossbaa676f2019-02-25 14:56:01 -0800628
Dan Willemsen633c5022019-04-12 11:11:38 -0700629 if len(params.ImplicitOutputs) != 0 {
630 t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
631 }
632
Paul Duffin709e0e32021-03-22 10:09:02 +0000633 AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
Dan Willemsen633c5022019-04-12 11:11:38 -0700634
635 if params.Deps != blueprint.DepsGCC {
636 t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
Colin Crossbaa676f2019-02-25 14:56:01 -0800637 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700638
639 rspFile2Content := ContentFromFileRuleForTests(t, rspFile2Params)
640 AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
Colin Crossfeec25b2019-01-30 17:32:39 -0800641 }
642
Colin Cross4c83e5c2019-02-25 14:54:28 -0800643 t.Run("module", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000644 outFile := "out/soong/.intermediates/foo/gen/foo"
Colin Crossce3a51d2021-03-19 16:22:12 -0700645 rspFile := "out/soong/.intermediates/foo/rsp"
646 rspFile2 := "out/soong/.intermediates/foo/rsp2"
647 module := result.ModuleForTests("foo", "")
648 check(t, module.Rule("rule").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
649 "cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
650 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Dan Willemsen633c5022019-04-12 11:11:38 -0700651 })
652 t.Run("sbox", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000653 outDir := "out/soong/.intermediates/foo_sbox"
Colin Crosse16ce362020-11-12 08:29:30 -0800654 outFile := filepath.Join(outDir, "gen/foo_sbox")
655 depFile := filepath.Join(outDir, "gen/foo_sbox.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700656 rspFile := filepath.Join(outDir, "rsp")
657 rspFile2 := filepath.Join(outDir, "rsp2")
658 manifest := filepath.Join(outDir, "sbox.textproto")
659 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
660 sandboxPath := shared.TempDirForOutDir("out/soong")
661
662 cmd := `rm -rf ` + outDir + `/gen && ` +
663 sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
664 module := result.ModuleForTests("foo_sbox", "")
665 check(t, module.Output("gen/foo_sbox").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
666 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
667 })
668 t.Run("sbox_inputs", func(t *testing.T) {
669 outDir := "out/soong/.intermediates/foo_sbox_inputs"
670 outFile := filepath.Join(outDir, "gen/foo_sbox_inputs")
671 depFile := filepath.Join(outDir, "gen/foo_sbox_inputs.d")
672 rspFile := filepath.Join(outDir, "rsp")
673 rspFile2 := filepath.Join(outDir, "rsp2")
Colin Crosse16ce362020-11-12 08:29:30 -0800674 manifest := filepath.Join(outDir, "sbox.textproto")
Paul Duffin709e0e32021-03-22 10:09:02 +0000675 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
676 sandboxPath := shared.TempDirForOutDir("out/soong")
Dan Willemsen633c5022019-04-12 11:11:38 -0700677
Colin Crosse16ce362020-11-12 08:29:30 -0800678 cmd := `rm -rf ` + outDir + `/gen && ` +
679 sbox + ` --sandbox-path ` + sandboxPath + ` --manifest ` + manifest
Dan Willemsen633c5022019-04-12 11:11:38 -0700680
Colin Crossce3a51d2021-03-19 16:22:12 -0700681 module := result.ModuleForTests("foo_sbox_inputs", "")
682 check(t, module.Output("gen/foo_sbox_inputs").RelativeToTop(), module.Output(rspFile2).RelativeToTop(),
683 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
Colin Cross4c83e5c2019-02-25 14:54:28 -0800684 })
685 t.Run("singleton", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000686 outFile := filepath.Join("out/soong/singleton/gen/baz")
Colin Crossce3a51d2021-03-19 16:22:12 -0700687 rspFile := filepath.Join("out/soong/singleton/rsp")
688 rspFile2 := filepath.Join("out/soong/singleton/rsp2")
689 singleton := result.SingletonForTests("rule_builder_test")
690 check(t, singleton.Rule("rule").RelativeToTop(), singleton.Output(rspFile2).RelativeToTop(),
691 "cp bar "+outFile+" @"+rspFile+" @"+rspFile2,
692 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Colin Cross4c83e5c2019-02-25 14:54:28 -0800693 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800694}
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700695
Colin Cross3d680512020-11-13 16:23:53 -0800696func TestRuleBuilderHashInputs(t *testing.T) {
697 // The basic idea here is to verify that the command (in the case of a
698 // non-sbox rule) or the sbox textproto manifest contain a hash of the
699 // inputs.
700
701 // By including a hash of the inputs, we cause the rule to re-run if
702 // the list of inputs changes because the command line or a dependency
703 // changes.
704
705 bp := `
706 rule_builder_test {
707 name: "hash0",
708 srcs: ["in1.txt", "in2.txt"],
709 }
710 rule_builder_test {
711 name: "hash0_sbox",
712 srcs: ["in1.txt", "in2.txt"],
713 sbox: true,
714 }
715 rule_builder_test {
716 name: "hash1",
717 srcs: ["in1.txt", "in2.txt", "in3.txt"],
718 }
719 rule_builder_test {
720 name: "hash1_sbox",
721 srcs: ["in1.txt", "in2.txt", "in3.txt"],
722 sbox: true,
723 }
724 `
725 testcases := []struct {
726 name string
727 expectedHash string
728 }{
729 {
730 name: "hash0",
731 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
732 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
733 },
734 {
735 name: "hash1",
736 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
737 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
738 },
739 }
740
Paul Duffin30ac3e72021-03-20 00:36:14 +0000741 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000742 prepareForRuleBuilderTest,
743 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000744 ).RunTest(t)
Colin Cross3d680512020-11-13 16:23:53 -0800745
746 for _, test := range testcases {
747 t.Run(test.name, func(t *testing.T) {
748 t.Run("sbox", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000749 gen := result.ModuleForTests(test.name+"_sbox", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800750 manifest := RuleBuilderSboxProtoForTests(t, gen.Output("sbox.textproto"))
751 hash := manifest.Commands[0].GetInputHash()
752
Paul Duffind250ff62021-03-16 21:51:29 +0000753 AssertStringEquals(t, "hash", test.expectedHash, hash)
Colin Cross3d680512020-11-13 16:23:53 -0800754 })
755 t.Run("", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000756 gen := result.ModuleForTests(test.name+"", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800757 command := gen.Output("gen/" + test.name).RuleParams.Command
Colin Cross3d680512020-11-13 16:23:53 -0800758 if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
759 t.Errorf("Expected command line to end with %q, got %q", w, g)
760 }
761 })
762 })
763 }
764}