blob: 2dc6a79541eb8f5474b87f3a948486dd19624e05 [file] [log] [blame]
Colin Cross2a076922018-10-04 23:28:25 -07001// Copyright 2018 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 genrule
16
17import (
Vinh Tran140d5882022-06-10 14:23:27 -040018 "fmt"
Colin Cross2a076922018-10-04 23:28:25 -070019 "os"
Paul Duffin672cb9f2021-03-03 02:30:37 +000020 "regexp"
Liz Kammer796921d2023-07-11 08:21:41 -040021 "strconv"
Colin Cross2a076922018-10-04 23:28:25 -070022 "testing"
23
24 "android/soong/android"
Colin Crossba71a3f2019-03-18 12:12:48 -070025
26 "github.com/google/blueprint/proptools"
Colin Cross2a076922018-10-04 23:28:25 -070027)
28
Colin Cross2a076922018-10-04 23:28:25 -070029func TestMain(m *testing.M) {
Paul Duffine66946b2021-03-16 12:38:33 +000030 os.Exit(m.Run())
Colin Cross2a076922018-10-04 23:28:25 -070031}
32
Paul Duffin89648f92021-03-20 00:36:55 +000033var prepareForGenRuleTest = android.GroupFixturePreparers(
Paul Duffin672cb9f2021-03-03 02:30:37 +000034 android.PrepareForTestWithArchMutator,
35 android.PrepareForTestWithDefaults,
Paul Duffin672cb9f2021-03-03 02:30:37 +000036 android.PrepareForTestWithFilegroup,
37 PrepareForTestWithGenRuleBuildComponents,
38 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000039 android.RegisterPrebuiltMutators(ctx)
Paul Duffin672cb9f2021-03-03 02:30:37 +000040 ctx.RegisterModuleType("tool", toolFactory)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000041 ctx.RegisterModuleType("prebuilt_tool", prebuiltToolFactory)
Colin Crossfa65cee2021-03-22 17:05:59 -070042 ctx.RegisterModuleType("output", outputProducerFactory)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +090043 ctx.RegisterModuleType("use_source", useSourceFactory)
Paul Duffin672cb9f2021-03-03 02:30:37 +000044 }),
45 android.FixtureMergeMockFs(android.MockFS{
46 "tool": nil,
47 "tool_file1": nil,
48 "tool_file2": nil,
49 "in1": nil,
50 "in2": nil,
51 "in1.txt": nil,
52 "in2.txt": nil,
53 "in3.txt": nil,
54 }),
55)
Martin Stjernholm710ec3a2020-01-16 15:12:04 +000056
Paul Duffin672cb9f2021-03-03 02:30:37 +000057func testGenruleBp() string {
58 return `
Colin Cross2a076922018-10-04 23:28:25 -070059 tool {
60 name: "tool",
61 }
62
63 filegroup {
64 name: "tool_files",
65 srcs: [
66 "tool_file1",
67 "tool_file2",
68 ],
69 }
70
71 filegroup {
72 name: "1tool_file",
73 srcs: [
74 "tool_file1",
75 ],
76 }
77
78 filegroup {
79 name: "ins",
80 srcs: [
81 "in1",
82 "in2",
83 ],
84 }
85
86 filegroup {
87 name: "1in",
88 srcs: [
89 "in1",
90 ],
91 }
92
93 filegroup {
94 name: "empty",
95 }
96 `
Colin Cross2a076922018-10-04 23:28:25 -070097}
98
99func TestGenruleCmd(t *testing.T) {
100 testcases := []struct {
Yu Liu6a7940c2023-05-09 17:12:22 -0700101 name string
102 moduleName string
103 prop string
Colin Cross2a076922018-10-04 23:28:25 -0700104
Colin Crossba71a3f2019-03-18 12:12:48 -0700105 allowMissingDependencies bool
106
Colin Cross2a076922018-10-04 23:28:25 -0700107 err string
108 expect string
109 }{
110 {
111 name: "empty location tool",
112 prop: `
113 tools: ["tool"],
114 out: ["out"],
115 cmd: "$(location) > $(out)",
116 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800117 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700118 },
119 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700120 name: "empty location tool2",
121 prop: `
122 tools: [":tool"],
123 out: ["out"],
124 cmd: "$(location) > $(out)",
125 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800126 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700127 },
128 {
Colin Cross2a076922018-10-04 23:28:25 -0700129 name: "empty location tool file",
130 prop: `
131 tool_files: ["tool_file1"],
132 out: ["out"],
133 cmd: "$(location) > $(out)",
134 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800135 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700136 },
137 {
138 name: "empty location tool file fg",
139 prop: `
140 tool_files: [":1tool_file"],
141 out: ["out"],
142 cmd: "$(location) > $(out)",
143 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800144 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700145 },
146 {
147 name: "empty location tool and tool file",
148 prop: `
149 tools: ["tool"],
150 tool_files: ["tool_file1"],
151 out: ["out"],
152 cmd: "$(location) > $(out)",
153 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800154 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700155 },
156 {
157 name: "tool",
158 prop: `
159 tools: ["tool"],
160 out: ["out"],
161 cmd: "$(location tool) > $(out)",
162 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800163 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700164 },
165 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700166 name: "tool2",
167 prop: `
168 tools: [":tool"],
169 out: ["out"],
170 cmd: "$(location :tool) > $(out)",
171 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800172 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700173 },
174 {
Colin Cross2a076922018-10-04 23:28:25 -0700175 name: "tool file",
176 prop: `
177 tool_files: ["tool_file1"],
178 out: ["out"],
179 cmd: "$(location tool_file1) > $(out)",
180 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800181 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700182 },
183 {
184 name: "tool file fg",
185 prop: `
186 tool_files: [":1tool_file"],
187 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700188 cmd: "$(location :1tool_file) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700189 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800190 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700191 },
192 {
193 name: "tool files",
194 prop: `
195 tool_files: [":tool_files"],
196 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700197 cmd: "$(locations :tool_files) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700198 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800199 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 __SBOX_SANDBOX_DIR__/tools/src/tool_file2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700200 },
201 {
202 name: "in1",
203 prop: `
204 srcs: ["in1"],
205 out: ["out"],
206 cmd: "cat $(in) > $(out)",
207 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800208 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700209 },
210 {
211 name: "in1 fg",
212 prop: `
213 srcs: [":1in"],
214 out: ["out"],
215 cmd: "cat $(in) > $(out)",
216 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800217 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700218 },
219 {
220 name: "ins",
221 prop: `
222 srcs: ["in1", "in2"],
223 out: ["out"],
224 cmd: "cat $(in) > $(out)",
225 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800226 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700227 },
228 {
229 name: "ins fg",
230 prop: `
231 srcs: [":ins"],
232 out: ["out"],
233 cmd: "cat $(in) > $(out)",
234 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800235 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700236 },
237 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700238 name: "location in1",
239 prop: `
240 srcs: ["in1"],
241 out: ["out"],
242 cmd: "cat $(location in1) > $(out)",
243 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800244 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700245 },
246 {
247 name: "location in1 fg",
248 prop: `
249 srcs: [":1in"],
250 out: ["out"],
251 cmd: "cat $(location :1in) > $(out)",
252 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800253 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700254 },
255 {
256 name: "location ins",
257 prop: `
258 srcs: ["in1", "in2"],
259 out: ["out"],
260 cmd: "cat $(location in1) > $(out)",
261 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800262 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700263 },
264 {
265 name: "location ins fg",
266 prop: `
267 srcs: [":ins"],
268 out: ["out"],
269 cmd: "cat $(locations :ins) > $(out)",
270 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800271 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700272 },
273 {
Colin Cross2a076922018-10-04 23:28:25 -0700274 name: "outs",
275 prop: `
276 out: ["out", "out2"],
277 cmd: "echo foo > $(out)",
278 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800279 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross2a076922018-10-04 23:28:25 -0700280 },
281 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700282 name: "location out",
283 prop: `
284 out: ["out", "out2"],
285 cmd: "echo foo > $(location out2)",
286 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800287 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross08f15ab2018-10-04 23:29:14 -0700288 },
289 {
Colin Cross2a076922018-10-04 23:28:25 -0700290 name: "gendir",
291 prop: `
292 out: ["out"],
293 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
294 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800295 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/foo && cp __SBOX_SANDBOX_DIR__/out/foo __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700296 },
Colin Cross70c47412021-03-12 17:48:14 -0800297 {
298 name: "$",
299 prop: `
300 out: ["out"],
301 cmd: "echo $$ > $(out)",
302 `,
303 expect: "echo $ > __SBOX_SANDBOX_DIR__/out/out",
304 },
Colin Cross2a076922018-10-04 23:28:25 -0700305
306 {
307 name: "error empty location",
308 prop: `
309 out: ["out"],
310 cmd: "$(location) > $(out)",
311 `,
312 err: "at least one `tools` or `tool_files` is required if $(location) is used",
313 },
314 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700315 name: "error empty location no files",
316 prop: `
317 tool_files: [":empty"],
318 out: ["out"],
319 cmd: "$(location) > $(out)",
320 `,
321 err: `default label ":empty" has no files`,
322 },
323 {
324 name: "error empty location multiple files",
325 prop: `
326 tool_files: [":tool_files"],
327 out: ["out"],
328 cmd: "$(location) > $(out)",
329 `,
330 err: `default label ":tool_files" has multiple files`,
331 },
332 {
Colin Cross2a076922018-10-04 23:28:25 -0700333 name: "error location",
334 prop: `
335 out: ["out"],
336 cmd: "echo foo > $(location missing)",
337 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000338 err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
Colin Cross2a076922018-10-04 23:28:25 -0700339 },
340 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700341 name: "error locations",
342 prop: `
343 out: ["out"],
344 cmd: "echo foo > $(locations missing)",
345 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000346 err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
Colin Cross08f15ab2018-10-04 23:29:14 -0700347 },
348 {
349 name: "error location no files",
350 prop: `
351 out: ["out"],
352 srcs: [":empty"],
353 cmd: "echo $(location :empty) > $(out)",
354 `,
355 err: `label ":empty" has no files`,
356 },
357 {
358 name: "error locations no files",
359 prop: `
360 out: ["out"],
361 srcs: [":empty"],
362 cmd: "echo $(locations :empty) > $(out)",
363 `,
364 err: `label ":empty" has no files`,
365 },
366 {
367 name: "error location multiple files",
368 prop: `
369 out: ["out"],
370 srcs: [":ins"],
371 cmd: "echo $(location :ins) > $(out)",
372 `,
373 err: `label ":ins" has multiple files`,
374 },
375 {
Colin Cross2a076922018-10-04 23:28:25 -0700376 name: "error variable",
377 prop: `
378 out: ["out"],
379 srcs: ["in1"],
380 cmd: "echo $(foo) > $(out)",
381 `,
382 err: `unknown variable '$(foo)'`,
383 },
384 {
Colin Cross2a076922018-10-04 23:28:25 -0700385 name: "error no out",
386 prop: `
387 cmd: "echo foo > $(out)",
388 `,
389 err: "must have at least one output file",
390 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700391 {
392 name: "srcs allow missing dependencies",
393 prop: `
394 srcs: [":missing"],
395 out: ["out"],
396 cmd: "cat $(location :missing) > $(out)",
397 `,
398
399 allowMissingDependencies: true,
400
Jihoon Kangc170af42022-08-20 05:26:38 +0000401 expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700402 },
403 {
404 name: "tool allow missing dependencies",
405 prop: `
406 tools: [":missing"],
407 out: ["out"],
408 cmd: "$(location :missing) > $(out)",
409 `,
410
411 allowMissingDependencies: true,
412
Jihoon Kangc170af42022-08-20 05:26:38 +0000413 expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700414 },
Colin Cross2a076922018-10-04 23:28:25 -0700415 }
416
417 for _, test := range testcases {
418 t.Run(test.name, func(t *testing.T) {
Yu Liu6a7940c2023-05-09 17:12:22 -0700419 moduleName := "gen"
420 if test.moduleName != "" {
421 moduleName = test.moduleName
422 }
423 bp := fmt.Sprintf(`
424 genrule {
425 name: "%s",
426 %s
427 }`, moduleName, test.prop)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000428 var expectedErrors []string
429 if test.err != "" {
430 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700431 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000432
Paul Duffin89648f92021-03-20 00:36:55 +0000433 result := android.GroupFixturePreparers(
434 prepareForGenRuleTest,
Paul Duffin672cb9f2021-03-03 02:30:37 +0000435 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
436 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
437 }),
Yu Liu6a7940c2023-05-09 17:12:22 -0700438 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
439 variables.GenruleSandboxing = proptools.BoolPtr(true)
440 }),
Paul Duffin672cb9f2021-03-03 02:30:37 +0000441 android.FixtureModifyContext(func(ctx *android.TestContext) {
442 ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
443 }),
444 ).
445 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
446 RunTestWithBp(t, testGenruleBp()+bp)
447
448 if expectedErrors != nil {
Colin Cross2a076922018-10-04 23:28:25 -0700449 return
450 }
451
Yu Liu6a7940c2023-05-09 17:12:22 -0700452 gen := result.Module(moduleName, "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000453 android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
Colin Cross2a076922018-10-04 23:28:25 -0700454 })
455 }
Colin Cross1a527682019-09-23 15:55:30 -0700456}
457
Bill Peckhamc087be12020-02-13 15:55:10 -0800458func TestGenruleHashInputs(t *testing.T) {
459
460 // The basic idea here is to verify that the sbox command (which is
461 // in the Command field of the generate rule) contains a hash of the
462 // inputs, but only if $(in) is not referenced in the genrule cmd
463 // property.
464
465 // By including a hash of the inputs, we cause the rule to re-run if
466 // the list of inputs changes (because the sbox command changes).
467
468 // However, if the genrule cmd property already contains $(in), then
469 // the dependency is already expressed, so we don't need to include the
470 // hash in that case.
471
472 bp := `
473 genrule {
474 name: "hash0",
475 srcs: ["in1.txt", "in2.txt"],
476 out: ["out"],
477 cmd: "echo foo > $(out)",
478 }
479 genrule {
480 name: "hash1",
481 srcs: ["*.txt"],
482 out: ["out"],
483 cmd: "echo bar > $(out)",
484 }
485 genrule {
486 name: "hash2",
487 srcs: ["*.txt"],
488 out: ["out"],
489 cmd: "echo $(in) > $(out)",
490 }
491 `
492 testcases := []struct {
493 name string
494 expectedHash string
495 }{
496 {
497 name: "hash0",
Colin Cross3d680512020-11-13 16:23:53 -0800498 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
499 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
Bill Peckhamc087be12020-02-13 15:55:10 -0800500 },
501 {
502 name: "hash1",
Colin Cross3d680512020-11-13 16:23:53 -0800503 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
504 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800505 },
506 {
507 name: "hash2",
Colin Cross3d680512020-11-13 16:23:53 -0800508 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
509 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800510 },
511 }
512
Paul Duffin89648f92021-03-20 00:36:55 +0000513 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Bill Peckhamc087be12020-02-13 15:55:10 -0800514
515 for _, test := range testcases {
516 t.Run(test.name, func(t *testing.T) {
Paul Duffine84b1332021-03-12 11:59:43 +0000517 gen := result.ModuleForTests(test.name, "")
Colin Crossf61d03d2023-11-02 16:56:39 -0700518 manifest := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
Colin Crosse16ce362020-11-12 08:29:30 -0800519 hash := manifest.Commands[0].GetInputHash()
Bill Peckhamc087be12020-02-13 15:55:10 -0800520
Paul Duffine84b1332021-03-12 11:59:43 +0000521 android.AssertStringEquals(t, "hash", test.expectedHash, hash)
Bill Peckhamc087be12020-02-13 15:55:10 -0800522 })
523 }
524}
525
Colin Cross1a527682019-09-23 15:55:30 -0700526func TestGenSrcs(t *testing.T) {
527 testcases := []struct {
528 name string
529 prop string
530
531 allowMissingDependencies bool
532
Liz Kammer796921d2023-07-11 08:21:41 -0400533 err string
534 cmds []string
535 deps []string
536 files []string
537 shards int
538 inputs []string
Colin Cross1a527682019-09-23 15:55:30 -0700539 }{
540 {
541 name: "gensrcs",
542 prop: `
543 tools: ["tool"],
544 srcs: ["in1.txt", "in2.txt"],
545 cmd: "$(location) $(in) > $(out)",
546 `,
547 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800548 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700549 },
Paul Duffine66946b2021-03-16 12:38:33 +0000550 deps: []string{
551 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
552 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
553 },
554 files: []string{
555 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
556 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
557 },
Colin Cross1a527682019-09-23 15:55:30 -0700558 },
559 {
560 name: "shards",
561 prop: `
562 tools: ["tool"],
563 srcs: ["in1.txt", "in2.txt", "in3.txt"],
564 cmd: "$(location) $(in) > $(out)",
565 shard_size: 2,
566 `,
567 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800568 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
569 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700570 },
Paul Duffine66946b2021-03-16 12:38:33 +0000571 deps: []string{
572 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
573 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
574 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
575 },
576 files: []string{
577 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
578 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
579 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
580 },
Colin Cross1a527682019-09-23 15:55:30 -0700581 },
Liz Kammer81fec182023-06-09 13:33:45 -0400582 {
583 name: "data",
584 prop: `
585 tools: ["tool"],
586 srcs: ["in1.txt", "in2.txt", "in3.txt"],
587 cmd: "$(location) $(in) --extra_input=$(location baz.txt) > $(out)",
588 data: ["baz.txt"],
589 shard_size: 2,
590 `,
591 cmds: []string{
592 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in1.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in1.h' && bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in2.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in2.h'",
593 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt --extra_input=baz.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
594 },
595 deps: []string{
596 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
597 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
598 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
599 },
600 files: []string{
601 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
602 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
603 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
604 },
Liz Kammer796921d2023-07-11 08:21:41 -0400605 shards: 2,
606 inputs: []string{
607 "baz.txt",
608 },
Liz Kammer81fec182023-06-09 13:33:45 -0400609 },
Colin Cross1a527682019-09-23 15:55:30 -0700610 }
611
Liz Kammer796921d2023-07-11 08:21:41 -0400612 checkInputs := func(t *testing.T, rule android.TestingBuildParams, inputs []string) {
613 t.Helper()
614 if len(inputs) == 0 {
615 return
616 }
617 inputBaseNames := map[string]bool{}
618 for _, f := range rule.Implicits {
619 inputBaseNames[f.Base()] = true
620 }
621 for _, f := range inputs {
622 if _, ok := inputBaseNames[f]; !ok {
623 t.Errorf("Expected to find input file %q for %q, but did not", f, rule.Description)
624 }
625 }
626 }
627
Colin Cross1a527682019-09-23 15:55:30 -0700628 for _, test := range testcases {
629 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700630 bp := "gensrcs {\n"
631 bp += `name: "gen",` + "\n"
632 bp += `output_extension: "h",` + "\n"
633 bp += test.prop
634 bp += "}\n"
635
Paul Duffin672cb9f2021-03-03 02:30:37 +0000636 var expectedErrors []string
637 if test.err != "" {
638 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700639 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000640
Paul Duffin89648f92021-03-20 00:36:55 +0000641 result := prepareForGenRuleTest.
Paul Duffin672cb9f2021-03-03 02:30:37 +0000642 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
643 RunTestWithBp(t, testGenruleBp()+bp)
644
Liz Kammer796921d2023-07-11 08:21:41 -0400645 mod := result.ModuleForTests("gen", "")
Paul Duffin672cb9f2021-03-03 02:30:37 +0000646 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700647 return
648 }
649
Liz Kammer796921d2023-07-11 08:21:41 -0400650 if test.shards > 0 {
651 for i := 0; i < test.shards; i++ {
652 r := mod.Rule("generator" + strconv.Itoa(i))
653 checkInputs(t, r, test.inputs)
654 }
655 } else {
656 r := mod.Rule("generator")
657 checkInputs(t, r, test.inputs)
658 }
659
Paul Duffin672cb9f2021-03-03 02:30:37 +0000660 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000661 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700662
Paul Duffine66946b2021-03-16 12:38:33 +0000663 android.AssertPathsRelativeToTopEquals(t, "deps", test.deps, gen.outputDeps)
Colin Cross1a527682019-09-23 15:55:30 -0700664
Paul Duffine66946b2021-03-16 12:38:33 +0000665 android.AssertPathsRelativeToTopEquals(t, "files", test.files, gen.outputFiles)
Colin Cross1a527682019-09-23 15:55:30 -0700666 })
667 }
Colin Cross2a076922018-10-04 23:28:25 -0700668}
669
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800670func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800671 bp := `
672 genrule_defaults {
673 name: "gen_defaults1",
674 cmd: "cp $(in) $(out)",
675 }
676
677 genrule_defaults {
678 name: "gen_defaults2",
679 srcs: ["in1"],
680 }
681
682 genrule {
683 name: "gen",
684 out: ["out"],
685 defaults: ["gen_defaults1", "gen_defaults2"],
686 }
687 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000688
Paul Duffin89648f92021-03-20 00:36:55 +0000689 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000690
691 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800692
Colin Crosse16ce362020-11-12 08:29:30 -0800693 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000694 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800695
696 expectedSrcs := []string{"in1"}
Paul Duffine84b1332021-03-12 11:59:43 +0000697 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800698}
699
Colin Crossfa65cee2021-03-22 17:05:59 -0700700func TestGenruleAllowMissingDependencies(t *testing.T) {
701 bp := `
702 output {
703 name: "disabled",
704 enabled: false,
705 }
706
707 genrule {
708 name: "gen",
709 srcs: [
710 ":disabled",
711 ],
712 out: ["out"],
713 cmd: "cat $(in) > $(out)",
714 }
715 `
Paul Duffin79abe572021-03-29 02:16:14 +0100716 result := android.GroupFixturePreparers(
717 prepareForGenRuleTest,
Colin Crossfa65cee2021-03-22 17:05:59 -0700718 android.FixtureModifyConfigAndContext(
719 func(config android.Config, ctx *android.TestContext) {
720 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
721 ctx.SetAllowMissingDependencies(true)
722 })).RunTestWithBp(t, bp)
723
724 gen := result.ModuleForTests("gen", "").Output("out")
725 if gen.Rule != android.ErrorRule {
726 t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
727 }
728}
729
Jooyung Han8c7e3ed2021-06-28 17:35:58 +0900730func TestGenruleOutputFiles(t *testing.T) {
731 bp := `
732 genrule {
733 name: "gen",
734 out: ["foo", "sub/bar"],
735 cmd: "echo foo > $(location foo) && echo bar > $(location sub/bar)",
736 }
737 use_source {
738 name: "gen_foo",
739 srcs: [":gen{foo}"],
740 }
741 use_source {
742 name: "gen_bar",
743 srcs: [":gen{sub/bar}"],
744 }
745 use_source {
746 name: "gen_all",
747 srcs: [":gen"],
748 }
749 `
750
751 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
752 android.AssertPathsRelativeToTopEquals(t,
753 "genrule.tag with output",
754 []string{"out/soong/.intermediates/gen/gen/foo"},
755 result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
756 android.AssertPathsRelativeToTopEquals(t,
757 "genrule.tag with output in subdir",
758 []string{"out/soong/.intermediates/gen/gen/sub/bar"},
759 result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
760 android.AssertPathsRelativeToTopEquals(t,
761 "genrule.tag with all",
762 []string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
763 result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
764}
765
Liz Kammerd38c87c2023-07-17 09:58:50 -0400766func TestGenruleInterface(t *testing.T) {
767 result := android.GroupFixturePreparers(
768 prepareForGenRuleTest,
769 android.FixtureMergeMockFs(android.MockFS{
770 "package-dir/Android.bp": []byte(`
771 genrule {
772 name: "module-name",
773 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
774 srcs: [
775 "src/foo.proto",
776 ],
777 out: ["proto.h", "bar/proto.h"],
778 export_include_dirs: [".", "bar"],
779 }
780 `),
781 }),
782 ).RunTest(t)
783
784 exportedIncludeDirs := []string{
785 "out/soong/.intermediates/package-dir/module-name/gen/package-dir",
786 "out/soong/.intermediates/package-dir/module-name/gen",
787 "out/soong/.intermediates/package-dir/module-name/gen/package-dir/bar",
788 "out/soong/.intermediates/package-dir/module-name/gen/bar",
789 }
790 gen := result.Module("module-name", "").(*Module)
791
792 android.AssertPathsRelativeToTopEquals(
793 t,
794 "include path",
795 exportedIncludeDirs,
796 gen.GeneratedHeaderDirs(),
797 )
798 android.AssertPathsRelativeToTopEquals(
799 t,
800 "files",
801 []string{
802 "out/soong/.intermediates/package-dir/module-name/gen/proto.h",
803 "out/soong/.intermediates/package-dir/module-name/gen/bar/proto.h",
804 },
805 gen.GeneratedSourceFiles(),
806 )
807}
808
Vinh Tran370e08c2022-09-23 18:09:01 -0400809func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
810 result := android.GroupFixturePreparers(
811 prepareForGenRuleTest,
812 android.FixtureMergeMockFs(android.MockFS{
813 "external-protos/path/Android.bp": []byte(`
814 filegroup {
815 name: "external-protos",
816 srcs: ["baz/baz.proto", "bar.proto"],
817 }
818 `),
819 "package-dir/Android.bp": []byte(`
820 gensrcs {
821 name: "module-name",
822 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
823 srcs: [
824 "src/foo.proto",
825 ":external-protos",
826 ],
827 output_extension: "proto.h",
828 }
829 `),
830 }),
831 ).RunTest(t)
832
833 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
834 gen := result.Module("module-name", "").(*Module)
835
836 android.AssertPathsRelativeToTopEquals(
837 t,
838 "include path",
839 []string{exportedIncludeDir},
840 gen.exportedIncludeDirs,
841 )
842 android.AssertPathsRelativeToTopEquals(
843 t,
844 "files",
845 []string{
846 exportedIncludeDir + "/package-dir/src/foo.proto.h",
847 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
848 exportedIncludeDir + "/external-protos/path/bar.proto.h",
849 },
850 gen.outputFiles,
851 )
852}
853
854func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
855 bp := `
856 gensrcs {
857 name: "module-name",
858 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
859 srcs: [
860 ":external-protos",
861 ],
862 output_extension: "proto.h",
863 }
864 `
865 result := android.GroupFixturePreparers(
866 prepareForGenRuleTest,
867 android.FixtureMergeMockFs(android.MockFS{
868 "external-protos/path/Android.bp": []byte(`
869 filegroup {
870 name: "external-protos",
871 srcs: ["foo/foo.proto", "bar.proto"],
872 }
873 `),
874 }),
875 ).RunTestWithBp(t, bp)
876
877 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
878 gen := result.Module("module-name", "").(*Module)
879
880 android.AssertPathsRelativeToTopEquals(
881 t,
882 "include path",
883 []string{exportedIncludeDir},
884 gen.exportedIncludeDirs,
885 )
886 android.AssertPathsRelativeToTopEquals(
887 t,
888 "files",
889 []string{
890 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
891 exportedIncludeDir + "/external-protos/path/bar.proto.h",
892 },
893 gen.outputFiles,
894 )
895}
896
Martin Stjernholmdbd814d2022-01-12 23:18:30 +0000897func TestPrebuiltTool(t *testing.T) {
898 testcases := []struct {
899 name string
900 bp string
901 expectedToolName string
902 }{
903 {
904 name: "source only",
905 bp: `
906 tool { name: "tool" }
907 `,
908 expectedToolName: "bin/tool",
909 },
910 {
911 name: "prebuilt only",
912 bp: `
913 prebuilt_tool { name: "tool" }
914 `,
915 expectedToolName: "prebuilt_bin/tool",
916 },
917 {
918 name: "source preferred",
919 bp: `
920 tool { name: "tool" }
921 prebuilt_tool { name: "tool" }
922 `,
923 expectedToolName: "bin/tool",
924 },
925 {
926 name: "prebuilt preferred",
927 bp: `
928 tool { name: "tool" }
929 prebuilt_tool { name: "tool", prefer: true }
930 `,
931 expectedToolName: "prebuilt_bin/prebuilt_tool",
932 },
933 {
934 name: "source disabled",
935 bp: `
936 tool { name: "tool", enabled: false }
937 prebuilt_tool { name: "tool" }
938 `,
939 expectedToolName: "prebuilt_bin/prebuilt_tool",
940 },
941 }
942
943 for _, test := range testcases {
944 t.Run(test.name, func(t *testing.T) {
945 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
946 genrule {
947 name: "gen",
948 tools: ["tool"],
949 out: ["foo"],
950 cmd: "$(location tool)",
951 }
952 `)
953 gen := result.Module("gen", "").(*Module)
954 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
955 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
956 })
957 }
958}
959
Jihoon Kangc170af42022-08-20 05:26:38 +0000960func TestGenruleWithGlobPaths(t *testing.T) {
961 testcases := []struct {
962 name string
963 bp string
964 additionalFiles android.MockFS
965 expectedCmd string
966 }{
967 {
968 name: "single file in directory with $ sign",
969 bp: `
970 genrule {
971 name: "gen",
972 srcs: ["inn*.txt"],
973 out: ["out.txt"],
974 cmd: "cp $(in) $(out)",
975 }
976 `,
977 additionalFiles: android.MockFS{"inn$1.txt": nil},
978 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
979 },
980 {
981 name: "multiple file in directory with $ sign",
982 bp: `
983 genrule {
984 name: "gen",
985 srcs: ["inn*.txt"],
986 out: ["."],
987 cmd: "cp $(in) $(out)",
988 }
989 `,
990 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
991 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
992 },
993 {
994 name: "file in directory with other shell unsafe character",
995 bp: `
996 genrule {
997 name: "gen",
998 srcs: ["inn*.txt"],
999 out: ["out.txt"],
1000 cmd: "cp $(in) $(out)",
1001 }
1002 `,
1003 additionalFiles: android.MockFS{"inn@1.txt": nil},
1004 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1005 },
1006 {
1007 name: "glob location param with filepath containing $",
1008 bp: `
1009 genrule {
1010 name: "gen",
1011 srcs: ["**/inn*"],
1012 out: ["."],
1013 cmd: "cp $(in) $(location **/inn*)",
1014 }
1015 `,
1016 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1017 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1018 },
1019 {
1020 name: "glob locations param with filepath containing $",
1021 bp: `
1022 genrule {
1023 name: "gen",
1024 tool_files: ["**/inn*"],
1025 out: ["out.txt"],
1026 cmd: "cp $(locations **/inn*) $(out)",
1027 }
1028 `,
1029 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1030 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1031 },
1032 }
1033
1034 for _, test := range testcases {
1035 t.Run(test.name, func(t *testing.T) {
1036 result := android.GroupFixturePreparers(
1037 prepareForGenRuleTest,
1038 android.FixtureMergeMockFs(test.additionalFiles),
1039 ).RunTestWithBp(t, test.bp)
1040 gen := result.Module("gen", "").(*Module)
1041 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1042 })
1043 }
1044}
1045
Colin Cross2a076922018-10-04 23:28:25 -07001046type testTool struct {
1047 android.ModuleBase
1048 outputFile android.Path
1049}
1050
1051func toolFactory() android.Module {
1052 module := &testTool{}
1053 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1054 return module
1055}
1056
Colin Cross2a076922018-10-04 23:28:25 -07001057func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001058 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001059}
1060
1061func (t *testTool) HostToolPath() android.OptionalPath {
1062 return android.OptionalPathForPath(t.outputFile)
1063}
1064
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001065type prebuiltTestTool struct {
1066 android.ModuleBase
1067 prebuilt android.Prebuilt
1068 testTool
1069}
1070
1071func (p *prebuiltTestTool) Name() string {
1072 return p.prebuilt.Name(p.ModuleBase.Name())
1073}
1074
1075func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1076 return &p.prebuilt
1077}
1078
1079func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1080 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1081}
1082
1083func prebuiltToolFactory() android.Module {
1084 module := &prebuiltTestTool{}
1085 android.InitPrebuiltModuleWithoutSrcs(module)
1086 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1087 return module
1088}
1089
Colin Crossfe17f6f2019-03-28 19:30:56 -07001090var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001091var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001092
1093type testOutputProducer struct {
1094 android.ModuleBase
1095 outputFile android.Path
1096}
1097
1098func outputProducerFactory() android.Module {
1099 module := &testOutputProducer{}
1100 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1101 return module
1102}
1103
1104func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1105 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1106}
1107
1108func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) {
1109 return android.Paths{t.outputFile}, nil
1110}
1111
1112var _ android.OutputFileProducer = (*testOutputProducer)(nil)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001113
1114type useSource struct {
1115 android.ModuleBase
1116 props struct {
1117 Srcs []string `android:"path"`
1118 }
1119 srcs android.Paths
1120}
1121
1122func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1123 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1124}
1125
1126func useSourceFactory() android.Module {
1127 module := &useSource{}
1128 module.AddProperties(&module.props)
1129 android.InitAndroidModule(module)
1130 return module
1131}