blob: e1a1e08c4fd36f202afa74e7ece2346d510d6473 [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
Sam Delmerico285b66a2023-09-25 12:13:17 +000031var (
32 pctx_ruleBuilderTest = NewPackageContext("android/soong/rule_builder")
33 pctx_ruleBuilderTestSubContext = NewPackageContext("android/soong/rule_builder/config")
34)
35
36func init() {
37 pctx_ruleBuilderTest.Import("android/soong/rule_builder/config")
38 pctx_ruleBuilderTest.StaticVariable("cmdFlags", "${config.ConfigFlags}")
39 pctx_ruleBuilderTestSubContext.StaticVariable("ConfigFlags", "--some-clang-flag")
40}
41
Colin Crossf1a035e2020-11-16 17:32:30 -080042func builderContext() BuilderContext {
43 return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
Colin Cross98be1bb2019-12-13 20:41:13 -080044 "ld": nil,
45 "a.o": nil,
46 "b.o": nil,
47 "cp": nil,
48 "a": nil,
49 "b": nil,
50 "ls": nil,
51 "turbine": nil,
52 "java": nil,
53 "javac": nil,
54 }))
Colin Cross69f59a32019-02-15 10:39:37 -080055}
56
Colin Cross758290d2019-02-01 16:42:32 -080057func ExampleRuleBuilder() {
Colin Crossf1a035e2020-11-16 17:32:30 -080058 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -080059
Colin Crossf1a035e2020-11-16 17:32:30 -080060 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -080061
62 rule.Command().
63 Tool(PathForSource(ctx, "ld")).
64 Inputs(PathsForTesting("a.o", "b.o")).
65 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -080066 rule.Command().Text("echo success")
67
68 // To add the command to the build graph:
Colin Crossf1a035e2020-11-16 17:32:30 -080069 // rule.Build("link", "link")
Colin Cross758290d2019-02-01 16:42:32 -080070
71 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
72 fmt.Printf("tools: %q\n", rule.Tools())
73 fmt.Printf("inputs: %q\n", rule.Inputs())
74 fmt.Printf("outputs: %q\n", rule.Outputs())
75
76 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -080077 // commands: "ld a.o b.o -o out/soong/linked && echo success"
Colin Cross758290d2019-02-01 16:42:32 -080078 // tools: ["ld"]
79 // inputs: ["a.o" "b.o"]
Colin Cross7b6a55f2021-11-09 12:34:39 -080080 // outputs: ["out/soong/linked"]
Colin Cross758290d2019-02-01 16:42:32 -080081}
82
Colin Cross5cb5b092019-02-02 21:25:18 -080083func ExampleRuleBuilder_Temporary() {
Colin Crossf1a035e2020-11-16 17:32:30 -080084 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -080085
Colin Crossf1a035e2020-11-16 17:32:30 -080086 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -080087
88 rule.Command().
89 Tool(PathForSource(ctx, "cp")).
90 Input(PathForSource(ctx, "a")).
91 Output(PathForOutput(ctx, "b"))
92 rule.Command().
93 Tool(PathForSource(ctx, "cp")).
94 Input(PathForOutput(ctx, "b")).
95 Output(PathForOutput(ctx, "c"))
96 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -080097
98 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
99 fmt.Printf("tools: %q\n", rule.Tools())
100 fmt.Printf("inputs: %q\n", rule.Inputs())
101 fmt.Printf("outputs: %q\n", rule.Outputs())
102
103 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800104 // commands: "cp a out/soong/b && cp out/soong/b out/soong/c"
Colin Cross5cb5b092019-02-02 21:25:18 -0800105 // tools: ["cp"]
106 // inputs: ["a"]
Colin Cross7b6a55f2021-11-09 12:34:39 -0800107 // outputs: ["out/soong/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800108}
109
110func ExampleRuleBuilder_DeleteTemporaryFiles() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800111 ctx := builderContext()
Colin Cross5cb5b092019-02-02 21:25:18 -0800112
Colin Crossf1a035e2020-11-16 17:32:30 -0800113 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800114
115 rule.Command().
116 Tool(PathForSource(ctx, "cp")).
117 Input(PathForSource(ctx, "a")).
118 Output(PathForOutput(ctx, "b"))
119 rule.Command().
120 Tool(PathForSource(ctx, "cp")).
121 Input(PathForOutput(ctx, "b")).
122 Output(PathForOutput(ctx, "c"))
123 rule.Temporary(PathForOutput(ctx, "b"))
Colin Cross5cb5b092019-02-02 21:25:18 -0800124 rule.DeleteTemporaryFiles()
125
126 fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
127 fmt.Printf("tools: %q\n", rule.Tools())
128 fmt.Printf("inputs: %q\n", rule.Inputs())
129 fmt.Printf("outputs: %q\n", rule.Outputs())
130
131 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800132 // 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 -0800133 // tools: ["cp"]
134 // inputs: ["a"]
Colin Cross7b6a55f2021-11-09 12:34:39 -0800135 // outputs: ["out/soong/c"]
Colin Cross5cb5b092019-02-02 21:25:18 -0800136}
137
Colin Crossdeabb942019-02-11 14:11:09 -0800138func ExampleRuleBuilder_Installs() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800139 ctx := builderContext()
Colin Crossdeabb942019-02-11 14:11:09 -0800140
Colin Crossf1a035e2020-11-16 17:32:30 -0800141 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800142
143 out := PathForOutput(ctx, "linked")
144
145 rule.Command().
146 Tool(PathForSource(ctx, "ld")).
147 Inputs(PathsForTesting("a.o", "b.o")).
148 FlagWithOutput("-o ", out)
149 rule.Install(out, "/bin/linked")
150 rule.Install(out, "/sbin/linked")
Colin Crossdeabb942019-02-11 14:11:09 -0800151
152 fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
153
154 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800155 // rule.Installs().String() = "out/soong/linked:/bin/linked out/soong/linked:/sbin/linked"
Colin Crossdeabb942019-02-11 14:11:09 -0800156}
157
Colin Cross758290d2019-02-01 16:42:32 -0800158func ExampleRuleBuilderCommand() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800159 ctx := builderContext()
Colin Cross758290d2019-02-01 16:42:32 -0800160
Colin Crossf1a035e2020-11-16 17:32:30 -0800161 rule := NewRuleBuilder(pctx, ctx)
Colin Cross69f59a32019-02-15 10:39:37 -0800162
Colin Cross758290d2019-02-01 16:42:32 -0800163 // chained
Colin Cross69f59a32019-02-15 10:39:37 -0800164 rule.Command().
165 Tool(PathForSource(ctx, "ld")).
166 Inputs(PathsForTesting("a.o", "b.o")).
167 FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800168
169 // unchained
170 cmd := rule.Command()
Colin Cross69f59a32019-02-15 10:39:37 -0800171 cmd.Tool(PathForSource(ctx, "ld"))
172 cmd.Inputs(PathsForTesting("a.o", "b.o"))
173 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800174
175 // mixed:
Colin Cross69f59a32019-02-15 10:39:37 -0800176 cmd = rule.Command().Tool(PathForSource(ctx, "ld"))
177 cmd.Inputs(PathsForTesting("a.o", "b.o"))
178 cmd.FlagWithOutput("-o ", PathForOutput(ctx, "linked"))
Colin Cross758290d2019-02-01 16:42:32 -0800179}
180
181func ExampleRuleBuilderCommand_Flag() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800182 ctx := builderContext()
183 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800184 Tool(PathForSource(ctx, "ls")).Flag("-l"))
Colin Cross758290d2019-02-01 16:42:32 -0800185 // Output:
186 // ls -l
187}
188
Colin Cross92b7d582019-03-29 15:32:51 -0700189func ExampleRuleBuilderCommand_Flags() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800190 ctx := builderContext()
191 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross92b7d582019-03-29 15:32:51 -0700192 Tool(PathForSource(ctx, "ls")).Flags([]string{"-l", "-a"}))
193 // Output:
194 // ls -l -a
195}
196
Colin Cross758290d2019-02-01 16:42:32 -0800197func ExampleRuleBuilderCommand_FlagWithArg() {
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")).
Colin Cross758290d2019-02-01 16:42:32 -0800201 FlagWithArg("--sort=", "time"))
202 // Output:
203 // ls --sort=time
204}
205
Colin Crossc7ed0042019-02-11 14:11:09 -0800206func ExampleRuleBuilderCommand_FlagForEachArg() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800207 ctx := builderContext()
208 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800209 Tool(PathForSource(ctx, "ls")).
Colin Crossc7ed0042019-02-11 14:11:09 -0800210 FlagForEachArg("--sort=", []string{"time", "size"}))
211 // Output:
212 // ls --sort=time --sort=size
213}
214
Colin Cross758290d2019-02-01 16:42:32 -0800215func ExampleRuleBuilderCommand_FlagForEachInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800216 ctx := builderContext()
217 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800218 Tool(PathForSource(ctx, "turbine")).
219 FlagForEachInput("--classpath ", PathsForTesting("a.jar", "b.jar")))
Colin Cross758290d2019-02-01 16:42:32 -0800220 // Output:
221 // turbine --classpath a.jar --classpath b.jar
222}
223
224func ExampleRuleBuilderCommand_FlagWithInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800225 ctx := builderContext()
226 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800227 Tool(PathForSource(ctx, "java")).
228 FlagWithInputList("-classpath=", PathsForTesting("a.jar", "b.jar"), ":"))
Colin Cross758290d2019-02-01 16:42:32 -0800229 // Output:
230 // java -classpath=a.jar:b.jar
231}
232
233func ExampleRuleBuilderCommand_FlagWithInput() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800234 ctx := builderContext()
235 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800236 Tool(PathForSource(ctx, "java")).
237 FlagWithInput("-classpath=", PathForSource(ctx, "a")))
Colin Cross758290d2019-02-01 16:42:32 -0800238 // Output:
239 // java -classpath=a
240}
241
242func ExampleRuleBuilderCommand_FlagWithList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800243 ctx := builderContext()
244 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross69f59a32019-02-15 10:39:37 -0800245 Tool(PathForSource(ctx, "ls")).
Colin Cross758290d2019-02-01 16:42:32 -0800246 FlagWithList("--sort=", []string{"time", "size"}, ","))
247 // Output:
248 // ls --sort=time,size
249}
250
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700251func ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800252 ctx := builderContext()
253 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700254 Tool(PathForSource(ctx, "javac")).
Colin Cross70c47412021-03-12 17:48:14 -0800255 FlagWithRspFileInputList("@", PathForOutput(ctx, "foo.rsp"), PathsForTesting("a.java", "b.java")).
256 String())
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700257 // Output:
Colin Cross7b6a55f2021-11-09 12:34:39 -0800258 // javac @out/soong/foo.rsp
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700259}
260
261func ExampleRuleBuilderCommand_String() {
Colin Crossf1a035e2020-11-16 17:32:30 -0800262 ctx := builderContext()
263 fmt.Println(NewRuleBuilder(pctx, ctx).Command().
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700264 Text("FOO=foo").
265 Text("echo $FOO").
266 String())
267 // Output:
268 // FOO=foo echo $FOO
269}
270
Colin Crossfeec25b2019-01-30 17:32:39 -0800271func TestRuleBuilder(t *testing.T) {
Colin Cross69f59a32019-02-15 10:39:37 -0800272 fs := map[string][]byte{
Colin Crossda71eda2020-02-21 16:55:19 -0800273 "dep_fixer": nil,
274 "input": nil,
275 "Implicit": nil,
276 "Input": nil,
277 "OrderOnly": nil,
278 "OrderOnlys": nil,
279 "Tool": nil,
280 "input2": nil,
281 "tool2": nil,
282 "input3": nil,
Colin Cross69f59a32019-02-15 10:39:37 -0800283 }
284
Colin Crossab020a72021-03-12 17:52:23 -0800285 pathCtx := PathContextForTesting(TestConfig("out_local", nil, "", fs))
Colin Crossf1a035e2020-11-16 17:32:30 -0800286 ctx := builderContextForTests{
287 PathContext: pathCtx,
288 }
Colin Cross69f59a32019-02-15 10:39:37 -0800289
Dan Willemsen633c5022019-04-12 11:11:38 -0700290 addCommands := func(rule *RuleBuilder) {
291 cmd := rule.Command().
Colin Crossab020a72021-03-12 17:52:23 -0800292 DepFile(PathForOutput(ctx, "module/DepFile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700293 Flag("Flag").
294 FlagWithArg("FlagWithArg=", "arg").
Colin Crossab020a72021-03-12 17:52:23 -0800295 FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "module/depfile")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700296 FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
Colin Crossab020a72021-03-12 17:52:23 -0800297 FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "module/output")).
298 FlagWithRspFileInputList("FlagWithRspFileInputList=", PathForOutput(ctx, "rsp"),
299 Paths{
300 PathForSource(ctx, "RspInput"),
301 PathForOutput(ctx, "other/RspOutput2"),
302 }).
Dan Willemsen633c5022019-04-12 11:11:38 -0700303 Implicit(PathForSource(ctx, "Implicit")).
Colin Crossab020a72021-03-12 17:52:23 -0800304 ImplicitDepFile(PathForOutput(ctx, "module/ImplicitDepFile")).
305 ImplicitOutput(PathForOutput(ctx, "module/ImplicitOutput")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700306 Input(PathForSource(ctx, "Input")).
Colin Crossab020a72021-03-12 17:52:23 -0800307 Output(PathForOutput(ctx, "module/Output")).
Colin Crossda71eda2020-02-21 16:55:19 -0800308 OrderOnly(PathForSource(ctx, "OrderOnly")).
Colin Crossae89abe2021-04-21 11:45:23 -0700309 Validation(PathForSource(ctx, "Validation")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700310 Text("Text").
311 Tool(PathForSource(ctx, "Tool"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800312
Dan Willemsen633c5022019-04-12 11:11:38 -0700313 rule.Command().
314 Text("command2").
Colin Crossab020a72021-03-12 17:52:23 -0800315 DepFile(PathForOutput(ctx, "module/depfile2")).
Dan Willemsen633c5022019-04-12 11:11:38 -0700316 Input(PathForSource(ctx, "input2")).
Colin Crossab020a72021-03-12 17:52:23 -0800317 Output(PathForOutput(ctx, "module/output2")).
Colin Crossda71eda2020-02-21 16:55:19 -0800318 OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Colin Crossae89abe2021-04-21 11:45:23 -0700319 Validations(PathsForSource(ctx, []string{"Validations"})).
Dan Willemsen633c5022019-04-12 11:11:38 -0700320 Tool(PathForSource(ctx, "tool2"))
Colin Crossfeec25b2019-01-30 17:32:39 -0800321
Dan Willemsen633c5022019-04-12 11:11:38 -0700322 // Test updates to the first command after the second command has been started
323 cmd.Text("after command2")
324 // Test updating a command when the previous update did not replace the cmd variable
325 cmd.Text("old cmd")
Colin Crossfeec25b2019-01-30 17:32:39 -0800326
Dan Willemsen633c5022019-04-12 11:11:38 -0700327 // Test a command that uses the output of a previous command as an input
328 rule.Command().
329 Text("command3").
330 Input(PathForSource(ctx, "input3")).
Colin Crossab020a72021-03-12 17:52:23 -0800331 Input(PathForOutput(ctx, "module/output2")).
332 Output(PathForOutput(ctx, "module/output3")).
333 Text(cmd.PathForInput(PathForSource(ctx, "input3"))).
334 Text(cmd.PathForOutput(PathForOutput(ctx, "module/output2")))
Colin Crossfeec25b2019-01-30 17:32:39 -0800335 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700336
Colin Cross69f59a32019-02-15 10:39:37 -0800337 wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
Colin Crossab020a72021-03-12 17:52:23 -0800338 wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
339 PathForOutput(ctx, "other/RspOutput2")}
340 wantOutputs := PathsForOutput(ctx, []string{
Cole Faust9a346f62024-01-18 20:12:02 +0000341 "module/ImplicitOutput", "module/Output", "module/output", "module/output2",
342 "module/output3"})
Colin Crossab020a72021-03-12 17:52:23 -0800343 wantDepFiles := PathsForOutput(ctx, []string{
344 "module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
Colin Cross69f59a32019-02-15 10:39:37 -0800345 wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
Colin Crossda71eda2020-02-21 16:55:19 -0800346 wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
Colin Crossae89abe2021-04-21 11:45:23 -0700347 wantValidations := PathsForSource(ctx, []string{"Validation", "Validations"})
Colin Crossfeec25b2019-01-30 17:32:39 -0800348
Dan Willemsen633c5022019-04-12 11:11:38 -0700349 t.Run("normal", func(t *testing.T) {
Colin Crossf1a035e2020-11-16 17:32:30 -0800350 rule := NewRuleBuilder(pctx, ctx)
Dan Willemsen633c5022019-04-12 11:11:38 -0700351 addCommands(rule)
Colin Cross1d2cf042019-03-29 15:33:06 -0700352
Dan Willemsen633c5022019-04-12 11:11:38 -0700353 wantCommands := []string{
Colin Cross7b6a55f2021-11-09 12:34:39 -0800354 "out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " +
355 "FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " +
Cole Faust9a346f62024-01-18 20:12:02 +0000356 "Input out_local/soong/module/Output Text Tool after command2 old cmd",
Colin Cross7b6a55f2021-11-09 12:34:39 -0800357 "command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2",
358 "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 -0700359 }
Colin Cross1d2cf042019-03-29 15:33:06 -0700360
Colin Cross7b6a55f2021-11-09 12:34:39 -0800361 wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
362 "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 -0800363
Paul Duffind250ff62021-03-16 21:51:29 +0000364 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700365
Paul Duffind250ff62021-03-16 21:51:29 +0000366 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800367 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000368 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000369 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
370 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
371 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700372 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Dan Willemsen633c5022019-04-12 11:11:38 -0700373
Paul Duffind250ff62021-03-16 21:51:29 +0000374 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700375 })
376
377 t.Run("sbox", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800378 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crosse16ce362020-11-12 08:29:30 -0800379 PathForOutput(ctx, "sbox.textproto"))
Dan Willemsen633c5022019-04-12 11:11:38 -0700380 addCommands(rule)
381
382 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800383 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
384 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800385 "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
Cole Faust9a346f62024-01-18 20:12:02 +0000386 "Text Tool after command2 old cmd",
Colin Crosse16ce362020-11-12 08:29:30 -0800387 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
Colin Crossab020a72021-03-12 17:52:23 -0800388 "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 -0700389 }
390
Colin Cross7b6a55f2021-11-09 12:34:39 -0800391 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 -0800392
Paul Duffind250ff62021-03-16 21:51:29 +0000393 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Dan Willemsen633c5022019-04-12 11:11:38 -0700394
Paul Duffind250ff62021-03-16 21:51:29 +0000395 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800396 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000397 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
398 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
399 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
400 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700401 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Dan Willemsen633c5022019-04-12 11:11:38 -0700402
Paul Duffind250ff62021-03-16 21:51:29 +0000403 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Dan Willemsen633c5022019-04-12 11:11:38 -0700404 })
Colin Crossba9e4032020-11-24 16:32:22 -0800405
406 t.Run("sbox tools", func(t *testing.T) {
Colin Crossab020a72021-03-12 17:52:23 -0800407 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
Colin Crossba9e4032020-11-24 16:32:22 -0800408 PathForOutput(ctx, "sbox.textproto")).SandboxTools()
409 addCommands(rule)
410
411 wantCommands := []string{
Colin Crossab020a72021-03-12 17:52:23 -0800412 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
413 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
Colin Cross7b6a55f2021-11-09 12:34:39 -0800414 "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
Cole Faust9a346f62024-01-18 20:12:02 +0000415 "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
Colin Crossba9e4032020-11-24 16:32:22 -0800416 "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 -0800417 "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 -0800418 }
419
420 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"
421
Paul Duffind250ff62021-03-16 21:51:29 +0000422 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
Colin Crossba9e4032020-11-24 16:32:22 -0800423
Paul Duffind250ff62021-03-16 21:51:29 +0000424 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
Colin Crossab020a72021-03-12 17:52:23 -0800425 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
Paul Duffind250ff62021-03-16 21:51:29 +0000426 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
427 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
428 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
429 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700430 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Colin Crossba9e4032020-11-24 16:32:22 -0800431
Paul Duffind250ff62021-03-16 21:51:29 +0000432 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
Colin Crossba9e4032020-11-24 16:32:22 -0800433 })
Colin Cross045bfd92021-03-24 16:38:03 -0700434
435 t.Run("sbox inputs", func(t *testing.T) {
436 rule := NewRuleBuilder(pctx, ctx).Sbox(PathForOutput(ctx, "module"),
437 PathForOutput(ctx, "sbox.textproto")).SandboxInputs()
438 addCommands(rule)
439
440 wantCommands := []string{
441 "__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
442 "FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
Cole Fauste8561c62023-11-30 17:26:37 -0800443 "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
Cole Faust9a346f62024-01-18 20:12:02 +0000444 "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
Colin Cross045bfd92021-03-24 16:38:03 -0700445 "command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
446 "command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
447 }
448
449 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"
450
451 AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
452
453 AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
454 AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
455 AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
Colin Cross045bfd92021-03-24 16:38:03 -0700456 AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
457 AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
458 AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
Colin Crossae89abe2021-04-21 11:45:23 -0700459 AssertDeepEquals(t, "rule.Validations()", wantValidations, rule.Validations())
Colin Cross045bfd92021-03-24 16:38:03 -0700460
461 AssertSame(t, "rule.depFileMergerCmd()", wantDepMergerCommand, rule.depFileMergerCmd(rule.DepFiles()).String())
462 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800463}
464
465func testRuleBuilderFactory() Module {
466 module := &testRuleBuilderModule{}
467 module.AddProperties(&module.properties)
468 InitAndroidModule(module)
469 return module
470}
471
472type testRuleBuilderModule struct {
473 ModuleBase
474 properties struct {
Sam Delmerico285b66a2023-09-25 12:13:17 +0000475 Srcs []string
476 Flags []string
Dan Willemsen633c5022019-04-12 11:11:38 -0700477
Cole Faust2f3791f2024-11-25 15:49:57 -0800478 Restat bool
479 Sbox bool
480 Sbox_inputs bool
Colin Crossfeec25b2019-01-30 17:32:39 -0800481 }
482}
483
484func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
Colin Cross3d680512020-11-13 16:23:53 -0800485 in := PathsForSource(ctx, t.properties.Srcs)
Colin Crossda6401b2021-04-21 11:32:19 -0700486 implicit := PathForSource(ctx, "implicit")
487 orderOnly := PathForSource(ctx, "orderonly")
Colin Crossae89abe2021-04-21 11:45:23 -0700488 validation := PathForSource(ctx, "validation")
Colin Crosse16ce362020-11-12 08:29:30 -0800489 out := PathForModuleOut(ctx, "gen", ctx.ModuleName())
490 outDep := PathForModuleOut(ctx, "gen", ctx.ModuleName()+".d")
491 outDir := PathForModuleOut(ctx, "gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700492 rspFile := PathForModuleOut(ctx, "rsp")
493 rspFile2 := PathForModuleOut(ctx, "rsp2")
494 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
495 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800496 manifestPath := PathForModuleOut(ctx, "sbox.textproto")
Colin Crossfeec25b2019-01-30 17:32:39 -0800497
Sam Delmerico285b66a2023-09-25 12:13:17 +0000498 testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags,
499 out, outDep, outDir,
Cole Faust2f3791f2024-11-25 15:49:57 -0800500 manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs,
Colin Crossda6401b2021-04-21 11:32:19 -0700501 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800502}
503
504type testRuleBuilderSingleton struct{}
505
506func testRuleBuilderSingletonFactory() Singleton {
507 return &testRuleBuilderSingleton{}
508}
509
510func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
Colin Crossda6401b2021-04-21 11:32:19 -0700511 in := PathsForSource(ctx, []string{"in"})
512 implicit := PathForSource(ctx, "implicit")
513 orderOnly := PathForSource(ctx, "orderonly")
Colin Crossae89abe2021-04-21 11:45:23 -0700514 validation := PathForSource(ctx, "validation")
Colin Crosse16ce362020-11-12 08:29:30 -0800515 out := PathForOutput(ctx, "singleton/gen/baz")
516 outDep := PathForOutput(ctx, "singleton/gen/baz.d")
517 outDir := PathForOutput(ctx, "singleton/gen")
Colin Crossce3a51d2021-03-19 16:22:12 -0700518 rspFile := PathForOutput(ctx, "singleton/rsp")
519 rspFile2 := PathForOutput(ctx, "singleton/rsp2")
520 rspFileContents := PathsForSource(ctx, []string{"rsp_in"})
521 rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
Colin Crosse16ce362020-11-12 08:29:30 -0800522 manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
Colin Crossda6401b2021-04-21 11:32:19 -0700523
Sam Delmerico285b66a2023-09-25 12:13:17 +0000524 testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir,
Cole Faust2f3791f2024-11-25 15:49:57 -0800525 manifestPath, true, false, false,
Colin Crossce3a51d2021-03-19 16:22:12 -0700526 rspFile, rspFileContents, rspFile2, rspFileContents2)
Colin Cross786cd6d2019-02-01 16:41:11 -0800527}
528
Colin Crossae89abe2021-04-21 11:45:23 -0700529func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path,
Sam Delmerico285b66a2023-09-25 12:13:17 +0000530 flags []string,
Colin Crossda6401b2021-04-21 11:32:19 -0700531 out, outDep, outDir, manifestPath WritablePath,
Cole Faust2f3791f2024-11-25 15:49:57 -0800532 restat, sbox, sboxInputs bool,
Colin Crossce3a51d2021-03-19 16:22:12 -0700533 rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
534
Sam Delmerico285b66a2023-09-25 12:13:17 +0000535 rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx)
Colin Cross786cd6d2019-02-01 16:41:11 -0800536
Dan Willemsen633c5022019-04-12 11:11:38 -0700537 if sbox {
Colin Crosse16ce362020-11-12 08:29:30 -0800538 rule.Sbox(outDir, manifestPath)
Colin Crossce3a51d2021-03-19 16:22:12 -0700539 if sboxInputs {
540 rule.SandboxInputs()
541 }
Dan Willemsen633c5022019-04-12 11:11:38 -0700542 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800543
Colin Crossce3a51d2021-03-19 16:22:12 -0700544 rule.Command().
545 Tool(PathForSource(ctx, "cp")).
Sam Delmerico285b66a2023-09-25 12:13:17 +0000546 Flags(flags).
Colin Crossce3a51d2021-03-19 16:22:12 -0700547 Inputs(in).
Colin Crossda6401b2021-04-21 11:32:19 -0700548 Implicit(implicit).
549 OrderOnly(orderOnly).
Colin Crossae89abe2021-04-21 11:45:23 -0700550 Validation(validation).
Colin Crossce3a51d2021-03-19 16:22:12 -0700551 Output(out).
552 ImplicitDepFile(outDep).
553 FlagWithRspFileInputList("@", rspFile, rspFileContents).
554 FlagWithRspFileInputList("@", rspFile2, rspFileContents2)
Dan Willemsen633c5022019-04-12 11:11:38 -0700555
556 if restat {
557 rule.Restat()
558 }
Colin Crossbaa676f2019-02-25 14:56:01 -0800559
Cole Faust2f3791f2024-11-25 15:49:57 -0800560 rule.Build("rule", "desc")
Colin Crossfeec25b2019-01-30 17:32:39 -0800561}
562
Paul Duffind250ff62021-03-16 21:51:29 +0000563var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
564 ctx.RegisterModuleType("rule_builder_test", testRuleBuilderFactory)
565 ctx.RegisterSingletonType("rule_builder_test", testRuleBuilderSingletonFactory)
566})
567
Colin Crossfeec25b2019-01-30 17:32:39 -0800568func TestRuleBuilder_Build(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000569 fs := MockFS{
Colin Crossda6401b2021-04-21 11:32:19 -0700570 "in": nil,
571 "cp": nil,
Colin Cross98be1bb2019-12-13 20:41:13 -0800572 }
573
Colin Crossfeec25b2019-01-30 17:32:39 -0800574 bp := `
575 rule_builder_test {
576 name: "foo",
Colin Crossda6401b2021-04-21 11:32:19 -0700577 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700578 restat: true,
579 }
580 rule_builder_test {
581 name: "foo_sbox",
Colin Crossda6401b2021-04-21 11:32:19 -0700582 srcs: ["in"],
Dan Willemsen633c5022019-04-12 11:11:38 -0700583 sbox: true,
Colin Crossfeec25b2019-01-30 17:32:39 -0800584 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700585 rule_builder_test {
586 name: "foo_sbox_inputs",
Colin Crossda6401b2021-04-21 11:32:19 -0700587 srcs: ["in"],
Colin Crossce3a51d2021-03-19 16:22:12 -0700588 sbox: true,
589 sbox_inputs: true,
590 }
Colin Crossfeec25b2019-01-30 17:32:39 -0800591 `
592
Paul Duffin30ac3e72021-03-20 00:36:14 +0000593 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000594 prepareForRuleBuilderTest,
595 FixtureWithRootAndroidBp(bp),
596 fs.AddToFixture(),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000597 ).RunTest(t)
Colin Crossfeec25b2019-01-30 17:32:39 -0800598
Colin Crossce3a51d2021-03-19 16:22:12 -0700599 check := func(t *testing.T, params TestingBuildParams, rspFile2Params TestingBuildParams,
600 wantCommand, wantOutput, wantDepfile, wantRspFile, wantRspFile2 string,
601 wantRestat bool, extraImplicits, extraCmdDeps []string) {
602
Dan Willemsenc89b6f12019-08-29 14:47:40 -0700603 t.Helper()
Colin Cross3d680512020-11-13 16:23:53 -0800604 command := params.RuleParams.Command
Colin Crosse16ce362020-11-12 08:29:30 -0800605 re := regexp.MustCompile(" # hash of input list: [a-z0-9]*$")
Colin Cross3d680512020-11-13 16:23:53 -0800606 command = re.ReplaceAllLiteralString(command, "")
Paul Duffind250ff62021-03-16 21:51:29 +0000607
608 AssertStringEquals(t, "RuleParams.Command", wantCommand, command)
Dan Willemsen633c5022019-04-12 11:11:38 -0700609
610 wantDeps := append([]string{"cp"}, extraCmdDeps...)
Paul Duffind250ff62021-03-16 21:51:29 +0000611 AssertArrayString(t, "RuleParams.CommandDeps", wantDeps, params.RuleParams.CommandDeps)
Dan Willemsen633c5022019-04-12 11:11:38 -0700612
Paul Duffind250ff62021-03-16 21:51:29 +0000613 AssertBoolEquals(t, "RuleParams.Restat", wantRestat, params.RuleParams.Restat)
Colin Crossfeec25b2019-01-30 17:32:39 -0800614
Colin Crossce3a51d2021-03-19 16:22:12 -0700615 wantInputs := []string{"rsp_in"}
616 AssertArrayString(t, "Inputs", wantInputs, params.Inputs.Strings())
617
Colin Crossda6401b2021-04-21 11:32:19 -0700618 wantImplicits := append([]string{"implicit", "in"}, extraImplicits...)
Colin Crossce3a51d2021-03-19 16:22:12 -0700619 // The second rsp file and the files listed in it should be in implicits
620 wantImplicits = append(wantImplicits, "rsp_in2", wantRspFile2)
Paul Duffin709e0e32021-03-22 10:09:02 +0000621 AssertPathsRelativeToTopEquals(t, "Implicits", wantImplicits, params.Implicits)
Colin Crossfeec25b2019-01-30 17:32:39 -0800622
Colin Crossda6401b2021-04-21 11:32:19 -0700623 wantOrderOnlys := []string{"orderonly"}
624 AssertPathsRelativeToTopEquals(t, "OrderOnly", wantOrderOnlys, params.OrderOnly)
625
Colin Crossae89abe2021-04-21 11:45:23 -0700626 wantValidations := []string{"validation"}
627 AssertPathsRelativeToTopEquals(t, "Validations", wantValidations, params.Validations)
628
Colin Crossce3a51d2021-03-19 16:22:12 -0700629 wantRspFileContent := "$in"
630 AssertStringEquals(t, "RspfileContent", wantRspFileContent, params.RuleParams.RspfileContent)
631
632 AssertStringEquals(t, "Rspfile", wantRspFile, params.RuleParams.Rspfile)
633
Paul Duffin709e0e32021-03-22 10:09:02 +0000634 AssertPathRelativeToTopEquals(t, "Output", wantOutput, params.Output)
Colin Crossbaa676f2019-02-25 14:56:01 -0800635
Dan Willemsen633c5022019-04-12 11:11:38 -0700636 if len(params.ImplicitOutputs) != 0 {
637 t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
638 }
639
Paul Duffin709e0e32021-03-22 10:09:02 +0000640 AssertPathRelativeToTopEquals(t, "Depfile", wantDepfile, params.Depfile)
Dan Willemsen633c5022019-04-12 11:11:38 -0700641
642 if params.Deps != blueprint.DepsGCC {
643 t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
Colin Crossbaa676f2019-02-25 14:56:01 -0800644 }
Colin Crossce3a51d2021-03-19 16:22:12 -0700645
Colin Crossf61d03d2023-11-02 16:56:39 -0700646 rspFile2Content := ContentFromFileRuleForTests(t, result.TestContext, rspFile2Params)
Colin Crossce3a51d2021-03-19 16:22:12 -0700647 AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
Colin Crossfeec25b2019-01-30 17:32:39 -0800648 }
649
Colin Cross4c83e5c2019-02-25 14:54:28 -0800650 t.Run("module", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000651 outFile := "out/soong/.intermediates/foo/gen/foo"
Colin Crossce3a51d2021-03-19 16:22:12 -0700652 rspFile := "out/soong/.intermediates/foo/rsp"
653 rspFile2 := "out/soong/.intermediates/foo/rsp2"
654 module := result.ModuleForTests("foo", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100655 check(t, module.Rule("rule"), module.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700656 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700657 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Dan Willemsen633c5022019-04-12 11:11:38 -0700658 })
659 t.Run("sbox", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000660 outDir := "out/soong/.intermediates/foo_sbox"
Colin Crosse52c2ac2022-03-28 17:03:35 -0700661 sboxOutDir := filepath.Join(outDir, "gen")
662 outFile := filepath.Join(sboxOutDir, "foo_sbox")
663 depFile := filepath.Join(sboxOutDir, "foo_sbox.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700664 rspFile := filepath.Join(outDir, "rsp")
665 rspFile2 := filepath.Join(outDir, "rsp2")
666 manifest := filepath.Join(outDir, "sbox.textproto")
667 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
668 sandboxPath := shared.TempDirForOutDir("out/soong")
669
Colin Crosse52c2ac2022-03-28 17:03:35 -0700670 cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
Colin Crossce3a51d2021-03-19 16:22:12 -0700671 module := result.ModuleForTests("foo_sbox", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100672 check(t, module.Output("gen/foo_sbox"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700673 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
674 })
675 t.Run("sbox_inputs", func(t *testing.T) {
676 outDir := "out/soong/.intermediates/foo_sbox_inputs"
Colin Crosse52c2ac2022-03-28 17:03:35 -0700677 sboxOutDir := filepath.Join(outDir, "gen")
678 outFile := filepath.Join(sboxOutDir, "foo_sbox_inputs")
679 depFile := filepath.Join(sboxOutDir, "foo_sbox_inputs.d")
Colin Crossce3a51d2021-03-19 16:22:12 -0700680 rspFile := filepath.Join(outDir, "rsp")
681 rspFile2 := filepath.Join(outDir, "rsp2")
Colin Crosse16ce362020-11-12 08:29:30 -0800682 manifest := filepath.Join(outDir, "sbox.textproto")
Paul Duffin709e0e32021-03-22 10:09:02 +0000683 sbox := filepath.Join("out", "soong", "host", result.Config.PrebuiltOS(), "bin/sbox")
684 sandboxPath := shared.TempDirForOutDir("out/soong")
Dan Willemsen633c5022019-04-12 11:11:38 -0700685
Colin Crosse52c2ac2022-03-28 17:03:35 -0700686 cmd := sbox + ` --sandbox-path ` + sandboxPath + ` --output-dir ` + sboxOutDir + ` --manifest ` + manifest
Dan Willemsen633c5022019-04-12 11:11:38 -0700687
Colin Crossce3a51d2021-03-19 16:22:12 -0700688 module := result.ModuleForTests("foo_sbox_inputs", "")
Paul Duffina71a67a2021-03-29 00:42:57 +0100689 check(t, module.Output("gen/foo_sbox_inputs"), module.Output(rspFile2),
Colin Crossce3a51d2021-03-19 16:22:12 -0700690 cmd, outFile, depFile, rspFile, rspFile2, false, []string{manifest}, []string{sbox})
Colin Cross4c83e5c2019-02-25 14:54:28 -0800691 })
692 t.Run("singleton", func(t *testing.T) {
Paul Duffin709e0e32021-03-22 10:09:02 +0000693 outFile := filepath.Join("out/soong/singleton/gen/baz")
Colin Crossce3a51d2021-03-19 16:22:12 -0700694 rspFile := filepath.Join("out/soong/singleton/rsp")
695 rspFile2 := filepath.Join("out/soong/singleton/rsp2")
696 singleton := result.SingletonForTests("rule_builder_test")
Paul Duffina71a67a2021-03-29 00:42:57 +0100697 check(t, singleton.Rule("rule"), singleton.Output(rspFile2),
Colin Crossda6401b2021-04-21 11:32:19 -0700698 "cp in "+outFile+" @"+rspFile+" @"+rspFile2,
Colin Crossce3a51d2021-03-19 16:22:12 -0700699 outFile, outFile+".d", rspFile, rspFile2, true, nil, nil)
Colin Cross4c83e5c2019-02-25 14:54:28 -0800700 })
Colin Crossfeec25b2019-01-30 17:32:39 -0800701}
Colin Cross0cb0d7b2019-07-11 10:59:15 -0700702
Colin Cross3d680512020-11-13 16:23:53 -0800703func TestRuleBuilderHashInputs(t *testing.T) {
704 // The basic idea here is to verify that the command (in the case of a
705 // non-sbox rule) or the sbox textproto manifest contain a hash of the
706 // inputs.
707
708 // By including a hash of the inputs, we cause the rule to re-run if
709 // the list of inputs changes because the command line or a dependency
710 // changes.
711
Colin Crossda6401b2021-04-21 11:32:19 -0700712 hashOf := func(s string) string {
713 sum := sha256.Sum256([]byte(s))
714 return hex.EncodeToString(sum[:])
715 }
716
Colin Cross3d680512020-11-13 16:23:53 -0800717 bp := `
718 rule_builder_test {
719 name: "hash0",
720 srcs: ["in1.txt", "in2.txt"],
721 }
722 rule_builder_test {
723 name: "hash0_sbox",
724 srcs: ["in1.txt", "in2.txt"],
725 sbox: true,
726 }
727 rule_builder_test {
728 name: "hash1",
729 srcs: ["in1.txt", "in2.txt", "in3.txt"],
730 }
731 rule_builder_test {
732 name: "hash1_sbox",
733 srcs: ["in1.txt", "in2.txt", "in3.txt"],
734 sbox: true,
735 }
736 `
737 testcases := []struct {
738 name string
739 expectedHash string
740 }{
741 {
Colin Crossda6401b2021-04-21 11:32:19 -0700742 name: "hash0",
743 expectedHash: hashOf("implicit\nin1.txt\nin2.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800744 },
745 {
Colin Crossda6401b2021-04-21 11:32:19 -0700746 name: "hash1",
747 expectedHash: hashOf("implicit\nin1.txt\nin2.txt\nin3.txt"),
Colin Cross3d680512020-11-13 16:23:53 -0800748 },
749 }
750
Paul Duffin30ac3e72021-03-20 00:36:14 +0000751 result := GroupFixturePreparers(
Paul Duffind250ff62021-03-16 21:51:29 +0000752 prepareForRuleBuilderTest,
753 FixtureWithRootAndroidBp(bp),
Paul Duffin30ac3e72021-03-20 00:36:14 +0000754 ).RunTest(t)
Colin Cross3d680512020-11-13 16:23:53 -0800755
756 for _, test := range testcases {
757 t.Run(test.name, func(t *testing.T) {
758 t.Run("sbox", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000759 gen := result.ModuleForTests(test.name+"_sbox", "")
Colin Crossf61d03d2023-11-02 16:56:39 -0700760 manifest := RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("sbox.textproto"))
Colin Crosse16ce362020-11-12 08:29:30 -0800761 hash := manifest.Commands[0].GetInputHash()
762
Paul Duffind250ff62021-03-16 21:51:29 +0000763 AssertStringEquals(t, "hash", test.expectedHash, hash)
Colin Cross3d680512020-11-13 16:23:53 -0800764 })
765 t.Run("", func(t *testing.T) {
Paul Duffind250ff62021-03-16 21:51:29 +0000766 gen := result.ModuleForTests(test.name+"", "")
Colin Crosse16ce362020-11-12 08:29:30 -0800767 command := gen.Output("gen/" + test.name).RuleParams.Command
Colin Cross3d680512020-11-13 16:23:53 -0800768 if g, w := command, " # hash of input list: "+test.expectedHash; !strings.HasSuffix(g, w) {
769 t.Errorf("Expected command line to end with %q, got %q", w, g)
770 }
771 })
772 })
773 }
774}