blob: 63f8fa9b82ed5e6ce0c60159ef2b4c4b9dbc15c3 [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"
Colin Cross2a076922018-10-04 23:28:25 -070021 "testing"
22
23 "android/soong/android"
Colin Crossba71a3f2019-03-18 12:12:48 -070024
25 "github.com/google/blueprint/proptools"
Colin Cross2a076922018-10-04 23:28:25 -070026)
27
Colin Cross2a076922018-10-04 23:28:25 -070028func TestMain(m *testing.M) {
Paul Duffine66946b2021-03-16 12:38:33 +000029 os.Exit(m.Run())
Colin Cross2a076922018-10-04 23:28:25 -070030}
31
Paul Duffin89648f92021-03-20 00:36:55 +000032var prepareForGenRuleTest = android.GroupFixturePreparers(
Paul Duffin672cb9f2021-03-03 02:30:37 +000033 android.PrepareForTestWithArchMutator,
34 android.PrepareForTestWithDefaults,
Paul Duffin672cb9f2021-03-03 02:30:37 +000035 android.PrepareForTestWithFilegroup,
36 PrepareForTestWithGenRuleBuildComponents,
37 android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000038 android.RegisterPrebuiltMutators(ctx)
Paul Duffin672cb9f2021-03-03 02:30:37 +000039 ctx.RegisterModuleType("tool", toolFactory)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +000040 ctx.RegisterModuleType("prebuilt_tool", prebuiltToolFactory)
Colin Crossfa65cee2021-03-22 17:05:59 -070041 ctx.RegisterModuleType("output", outputProducerFactory)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +090042 ctx.RegisterModuleType("use_source", useSourceFactory)
Paul Duffin672cb9f2021-03-03 02:30:37 +000043 }),
44 android.FixtureMergeMockFs(android.MockFS{
45 "tool": nil,
46 "tool_file1": nil,
47 "tool_file2": nil,
48 "in1": nil,
49 "in2": nil,
50 "in1.txt": nil,
51 "in2.txt": nil,
52 "in3.txt": nil,
53 }),
54)
Martin Stjernholm710ec3a2020-01-16 15:12:04 +000055
Paul Duffin672cb9f2021-03-03 02:30:37 +000056func testGenruleBp() string {
57 return `
Colin Cross2a076922018-10-04 23:28:25 -070058 tool {
59 name: "tool",
60 }
61
62 filegroup {
63 name: "tool_files",
64 srcs: [
65 "tool_file1",
66 "tool_file2",
67 ],
68 }
69
70 filegroup {
71 name: "1tool_file",
72 srcs: [
73 "tool_file1",
74 ],
75 }
76
77 filegroup {
78 name: "ins",
79 srcs: [
80 "in1",
81 "in2",
82 ],
83 }
84
85 filegroup {
86 name: "1in",
87 srcs: [
88 "in1",
89 ],
90 }
91
92 filegroup {
93 name: "empty",
94 }
95 `
Colin Cross2a076922018-10-04 23:28:25 -070096}
97
98func TestGenruleCmd(t *testing.T) {
99 testcases := []struct {
100 name string
101 prop string
102
Colin Crossba71a3f2019-03-18 12:12:48 -0700103 allowMissingDependencies bool
104
Colin Cross2a076922018-10-04 23:28:25 -0700105 err string
106 expect string
107 }{
108 {
109 name: "empty location tool",
110 prop: `
111 tools: ["tool"],
112 out: ["out"],
113 cmd: "$(location) > $(out)",
114 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800115 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700116 },
117 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700118 name: "empty location tool2",
119 prop: `
120 tools: [":tool"],
121 out: ["out"],
122 cmd: "$(location) > $(out)",
123 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800124 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700125 },
126 {
Colin Cross2a076922018-10-04 23:28:25 -0700127 name: "empty location tool file",
128 prop: `
129 tool_files: ["tool_file1"],
130 out: ["out"],
131 cmd: "$(location) > $(out)",
132 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800133 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700134 },
135 {
136 name: "empty location tool file fg",
137 prop: `
138 tool_files: [":1tool_file"],
139 out: ["out"],
140 cmd: "$(location) > $(out)",
141 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800142 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700143 },
144 {
145 name: "empty location tool and tool file",
146 prop: `
147 tools: ["tool"],
148 tool_files: ["tool_file1"],
149 out: ["out"],
150 cmd: "$(location) > $(out)",
151 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800152 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700153 },
154 {
155 name: "tool",
156 prop: `
157 tools: ["tool"],
158 out: ["out"],
159 cmd: "$(location tool) > $(out)",
160 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800161 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700162 },
163 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700164 name: "tool2",
165 prop: `
166 tools: [":tool"],
167 out: ["out"],
168 cmd: "$(location :tool) > $(out)",
169 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800170 expect: "__SBOX_SANDBOX_DIR__/tools/out/bin/tool > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700171 },
172 {
Colin Cross2a076922018-10-04 23:28:25 -0700173 name: "tool file",
174 prop: `
175 tool_files: ["tool_file1"],
176 out: ["out"],
177 cmd: "$(location tool_file1) > $(out)",
178 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800179 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700180 },
181 {
182 name: "tool file fg",
183 prop: `
184 tool_files: [":1tool_file"],
185 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700186 cmd: "$(location :1tool_file) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700187 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800188 expect: "__SBOX_SANDBOX_DIR__/tools/src/tool_file1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700189 },
190 {
191 name: "tool files",
192 prop: `
193 tool_files: [":tool_files"],
194 out: ["out"],
Colin Cross08f15ab2018-10-04 23:29:14 -0700195 cmd: "$(locations :tool_files) > $(out)",
Colin Cross2a076922018-10-04 23:28:25 -0700196 `,
Colin Crossba9e4032020-11-24 16:32:22 -0800197 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 -0700198 },
199 {
200 name: "in1",
201 prop: `
202 srcs: ["in1"],
203 out: ["out"],
204 cmd: "cat $(in) > $(out)",
205 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800206 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700207 },
208 {
209 name: "in1 fg",
210 prop: `
211 srcs: [":1in"],
212 out: ["out"],
213 cmd: "cat $(in) > $(out)",
214 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800215 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700216 },
217 {
218 name: "ins",
219 prop: `
220 srcs: ["in1", "in2"],
221 out: ["out"],
222 cmd: "cat $(in) > $(out)",
223 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800224 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700225 },
226 {
227 name: "ins fg",
228 prop: `
229 srcs: [":ins"],
230 out: ["out"],
231 cmd: "cat $(in) > $(out)",
232 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800233 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross2a076922018-10-04 23:28:25 -0700234 },
235 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700236 name: "location in1",
237 prop: `
238 srcs: ["in1"],
239 out: ["out"],
240 cmd: "cat $(location in1) > $(out)",
241 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800242 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700243 },
244 {
245 name: "location in1 fg",
246 prop: `
247 srcs: [":1in"],
248 out: ["out"],
249 cmd: "cat $(location :1in) > $(out)",
250 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800251 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700252 },
253 {
254 name: "location ins",
255 prop: `
256 srcs: ["in1", "in2"],
257 out: ["out"],
258 cmd: "cat $(location in1) > $(out)",
259 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800260 expect: "cat in1 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700261 },
262 {
263 name: "location ins fg",
264 prop: `
265 srcs: [":ins"],
266 out: ["out"],
267 cmd: "cat $(locations :ins) > $(out)",
268 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800269 expect: "cat in1 in2 > __SBOX_SANDBOX_DIR__/out/out",
Colin Cross08f15ab2018-10-04 23:29:14 -0700270 },
271 {
Colin Cross2a076922018-10-04 23:28:25 -0700272 name: "outs",
273 prop: `
274 out: ["out", "out2"],
275 cmd: "echo foo > $(out)",
276 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800277 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross2a076922018-10-04 23:28:25 -0700278 },
279 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700280 name: "location out",
281 prop: `
282 out: ["out", "out2"],
283 cmd: "echo foo > $(location out2)",
284 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800285 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
Colin Cross08f15ab2018-10-04 23:29:14 -0700286 },
287 {
Colin Cross2a076922018-10-04 23:28:25 -0700288 name: "depfile",
289 prop: `
290 out: ["out"],
291 depfile: true,
292 cmd: "echo foo > $(out) && touch $(depfile)",
293 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800294 expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out && touch __SBOX_DEPFILE__",
Colin Cross2a076922018-10-04 23:28:25 -0700295 },
296 {
297 name: "gendir",
298 prop: `
299 out: ["out"],
300 cmd: "echo foo > $(genDir)/foo && cp $(genDir)/foo $(out)",
301 `,
Colin Crosse16ce362020-11-12 08:29:30 -0800302 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 -0700303 },
Colin Cross70c47412021-03-12 17:48:14 -0800304 {
305 name: "$",
306 prop: `
307 out: ["out"],
308 cmd: "echo $$ > $(out)",
309 `,
310 expect: "echo $ > __SBOX_SANDBOX_DIR__/out/out",
311 },
Colin Cross2a076922018-10-04 23:28:25 -0700312
313 {
314 name: "error empty location",
315 prop: `
316 out: ["out"],
317 cmd: "$(location) > $(out)",
318 `,
319 err: "at least one `tools` or `tool_files` is required if $(location) is used",
320 },
321 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700322 name: "error empty location no files",
323 prop: `
324 tool_files: [":empty"],
325 out: ["out"],
326 cmd: "$(location) > $(out)",
327 `,
328 err: `default label ":empty" has no files`,
329 },
330 {
331 name: "error empty location multiple files",
332 prop: `
333 tool_files: [":tool_files"],
334 out: ["out"],
335 cmd: "$(location) > $(out)",
336 `,
337 err: `default label ":tool_files" has multiple files`,
338 },
339 {
Colin Cross2a076922018-10-04 23:28:25 -0700340 name: "error location",
341 prop: `
342 out: ["out"],
343 cmd: "echo foo > $(location missing)",
344 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000345 err: `unknown location label "missing" is not in srcs, out, tools or tool_files.`,
Colin Cross2a076922018-10-04 23:28:25 -0700346 },
347 {
Colin Cross08f15ab2018-10-04 23:29:14 -0700348 name: "error locations",
349 prop: `
350 out: ["out"],
351 cmd: "echo foo > $(locations missing)",
352 `,
Anton Hanssonbebf5262022-02-23 11:42:38 +0000353 err: `unknown locations label "missing" is not in srcs, out, tools or tool_files`,
Colin Cross08f15ab2018-10-04 23:29:14 -0700354 },
355 {
356 name: "error location no files",
357 prop: `
358 out: ["out"],
359 srcs: [":empty"],
360 cmd: "echo $(location :empty) > $(out)",
361 `,
362 err: `label ":empty" has no files`,
363 },
364 {
365 name: "error locations no files",
366 prop: `
367 out: ["out"],
368 srcs: [":empty"],
369 cmd: "echo $(locations :empty) > $(out)",
370 `,
371 err: `label ":empty" has no files`,
372 },
373 {
374 name: "error location multiple files",
375 prop: `
376 out: ["out"],
377 srcs: [":ins"],
378 cmd: "echo $(location :ins) > $(out)",
379 `,
380 err: `label ":ins" has multiple files`,
381 },
382 {
Colin Cross2a076922018-10-04 23:28:25 -0700383 name: "error variable",
384 prop: `
385 out: ["out"],
386 srcs: ["in1"],
387 cmd: "echo $(foo) > $(out)",
388 `,
389 err: `unknown variable '$(foo)'`,
390 },
391 {
392 name: "error depfile",
393 prop: `
394 out: ["out"],
395 cmd: "echo foo > $(out) && touch $(depfile)",
396 `,
397 err: "$(depfile) used without depfile property",
398 },
399 {
400 name: "error no depfile",
401 prop: `
402 out: ["out"],
403 depfile: true,
404 cmd: "echo foo > $(out)",
405 `,
406 err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
407 },
408 {
409 name: "error no out",
410 prop: `
411 cmd: "echo foo > $(out)",
412 `,
413 err: "must have at least one output file",
414 },
Colin Crossba71a3f2019-03-18 12:12:48 -0700415 {
416 name: "srcs allow missing dependencies",
417 prop: `
418 srcs: [":missing"],
419 out: ["out"],
420 cmd: "cat $(location :missing) > $(out)",
421 `,
422
423 allowMissingDependencies: true,
424
Jihoon Kangc170af42022-08-20 05:26:38 +0000425 expect: "cat '***missing srcs :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700426 },
427 {
428 name: "tool allow missing dependencies",
429 prop: `
430 tools: [":missing"],
431 out: ["out"],
432 cmd: "$(location :missing) > $(out)",
433 `,
434
435 allowMissingDependencies: true,
436
Jihoon Kangc170af42022-08-20 05:26:38 +0000437 expect: "'***missing tool :missing***' > __SBOX_SANDBOX_DIR__/out/out",
Colin Crossba71a3f2019-03-18 12:12:48 -0700438 },
Colin Cross2a076922018-10-04 23:28:25 -0700439 }
440
441 for _, test := range testcases {
442 t.Run(test.name, func(t *testing.T) {
Colin Cross2a076922018-10-04 23:28:25 -0700443 bp := "genrule {\n"
444 bp += "name: \"gen\",\n"
445 bp += test.prop
446 bp += "}\n"
447
Paul Duffin672cb9f2021-03-03 02:30:37 +0000448 var expectedErrors []string
449 if test.err != "" {
450 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross2a076922018-10-04 23:28:25 -0700451 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000452
Paul Duffin89648f92021-03-20 00:36:55 +0000453 result := android.GroupFixturePreparers(
454 prepareForGenRuleTest,
Paul Duffin672cb9f2021-03-03 02:30:37 +0000455 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
456 variables.Allow_missing_dependencies = proptools.BoolPtr(test.allowMissingDependencies)
457 }),
458 android.FixtureModifyContext(func(ctx *android.TestContext) {
459 ctx.SetAllowMissingDependencies(test.allowMissingDependencies)
460 }),
461 ).
462 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
463 RunTestWithBp(t, testGenruleBp()+bp)
464
465 if expectedErrors != nil {
Colin Cross2a076922018-10-04 23:28:25 -0700466 return
467 }
468
Paul Duffin672cb9f2021-03-03 02:30:37 +0000469 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000470 android.AssertStringEquals(t, "raw commands", test.expect, gen.rawCommands[0])
Colin Cross2a076922018-10-04 23:28:25 -0700471 })
472 }
Colin Cross1a527682019-09-23 15:55:30 -0700473}
474
Bill Peckhamc087be12020-02-13 15:55:10 -0800475func TestGenruleHashInputs(t *testing.T) {
476
477 // The basic idea here is to verify that the sbox command (which is
478 // in the Command field of the generate rule) contains a hash of the
479 // inputs, but only if $(in) is not referenced in the genrule cmd
480 // property.
481
482 // By including a hash of the inputs, we cause the rule to re-run if
483 // the list of inputs changes (because the sbox command changes).
484
485 // However, if the genrule cmd property already contains $(in), then
486 // the dependency is already expressed, so we don't need to include the
487 // hash in that case.
488
489 bp := `
490 genrule {
491 name: "hash0",
492 srcs: ["in1.txt", "in2.txt"],
493 out: ["out"],
494 cmd: "echo foo > $(out)",
495 }
496 genrule {
497 name: "hash1",
498 srcs: ["*.txt"],
499 out: ["out"],
500 cmd: "echo bar > $(out)",
501 }
502 genrule {
503 name: "hash2",
504 srcs: ["*.txt"],
505 out: ["out"],
506 cmd: "echo $(in) > $(out)",
507 }
508 `
509 testcases := []struct {
510 name string
511 expectedHash string
512 }{
513 {
514 name: "hash0",
Colin Cross3d680512020-11-13 16:23:53 -0800515 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt' | sha256sum
516 expectedHash: "18da75b9b1cc74b09e365b4ca2e321b5d618f438cc632b387ad9dc2ab4b20e9d",
Bill Peckhamc087be12020-02-13 15:55:10 -0800517 },
518 {
519 name: "hash1",
Colin Cross3d680512020-11-13 16:23:53 -0800520 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
521 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800522 },
523 {
524 name: "hash2",
Colin Cross3d680512020-11-13 16:23:53 -0800525 // sha256 value obtained from: echo -en 'in1.txt\nin2.txt\nin3.txt' | sha256sum
526 expectedHash: "a38d432a4b19df93140e1f1fe26c97ff0387dae01fe506412b47208f0595fb45",
Bill Peckhamc087be12020-02-13 15:55:10 -0800527 },
528 }
529
Paul Duffin89648f92021-03-20 00:36:55 +0000530 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Bill Peckhamc087be12020-02-13 15:55:10 -0800531
532 for _, test := range testcases {
533 t.Run(test.name, func(t *testing.T) {
Paul Duffine84b1332021-03-12 11:59:43 +0000534 gen := result.ModuleForTests(test.name, "")
Colin Crosse16ce362020-11-12 08:29:30 -0800535 manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
536 hash := manifest.Commands[0].GetInputHash()
Bill Peckhamc087be12020-02-13 15:55:10 -0800537
Paul Duffine84b1332021-03-12 11:59:43 +0000538 android.AssertStringEquals(t, "hash", test.expectedHash, hash)
Bill Peckhamc087be12020-02-13 15:55:10 -0800539 })
540 }
541}
542
Colin Cross1a527682019-09-23 15:55:30 -0700543func TestGenSrcs(t *testing.T) {
544 testcases := []struct {
545 name string
546 prop string
547
548 allowMissingDependencies bool
549
550 err string
551 cmds []string
552 deps []string
553 files []string
554 }{
555 {
556 name: "gensrcs",
557 prop: `
558 tools: ["tool"],
559 srcs: ["in1.txt", "in2.txt"],
560 cmd: "$(location) $(in) > $(out)",
561 `,
562 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800563 "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 -0700564 },
Paul Duffine66946b2021-03-16 12:38:33 +0000565 deps: []string{
566 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
567 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
568 },
569 files: []string{
570 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
571 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
572 },
Colin Cross1a527682019-09-23 15:55:30 -0700573 },
574 {
575 name: "shards",
576 prop: `
577 tools: ["tool"],
578 srcs: ["in1.txt", "in2.txt", "in3.txt"],
579 cmd: "$(location) $(in) > $(out)",
580 shard_size: 2,
581 `,
582 cmds: []string{
Colin Crossba9e4032020-11-24 16:32:22 -0800583 "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'",
584 "bash -c '__SBOX_SANDBOX_DIR__/tools/out/bin/tool in3.txt > __SBOX_SANDBOX_DIR__/out/in3.h'",
Colin Cross1a527682019-09-23 15:55:30 -0700585 },
Paul Duffine66946b2021-03-16 12:38:33 +0000586 deps: []string{
587 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
588 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
589 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
590 },
591 files: []string{
592 "out/soong/.intermediates/gen/gen/gensrcs/in1.h",
593 "out/soong/.intermediates/gen/gen/gensrcs/in2.h",
594 "out/soong/.intermediates/gen/gen/gensrcs/in3.h",
595 },
Colin Cross1a527682019-09-23 15:55:30 -0700596 },
597 }
598
599 for _, test := range testcases {
600 t.Run(test.name, func(t *testing.T) {
Colin Cross1a527682019-09-23 15:55:30 -0700601 bp := "gensrcs {\n"
602 bp += `name: "gen",` + "\n"
603 bp += `output_extension: "h",` + "\n"
604 bp += test.prop
605 bp += "}\n"
606
Paul Duffin672cb9f2021-03-03 02:30:37 +0000607 var expectedErrors []string
608 if test.err != "" {
609 expectedErrors = append(expectedErrors, regexp.QuoteMeta(test.err))
Colin Cross1a527682019-09-23 15:55:30 -0700610 }
Paul Duffin672cb9f2021-03-03 02:30:37 +0000611
Paul Duffin89648f92021-03-20 00:36:55 +0000612 result := prepareForGenRuleTest.
Paul Duffin672cb9f2021-03-03 02:30:37 +0000613 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
614 RunTestWithBp(t, testGenruleBp()+bp)
615
616 if expectedErrors != nil {
Colin Cross1a527682019-09-23 15:55:30 -0700617 return
618 }
619
Paul Duffin672cb9f2021-03-03 02:30:37 +0000620 gen := result.Module("gen", "").(*Module)
Paul Duffine84b1332021-03-12 11:59:43 +0000621 android.AssertDeepEquals(t, "cmd", test.cmds, gen.rawCommands)
Colin Cross1a527682019-09-23 15:55:30 -0700622
Paul Duffine66946b2021-03-16 12:38:33 +0000623 android.AssertPathsRelativeToTopEquals(t, "deps", test.deps, gen.outputDeps)
Colin Cross1a527682019-09-23 15:55:30 -0700624
Paul Duffine66946b2021-03-16 12:38:33 +0000625 android.AssertPathsRelativeToTopEquals(t, "files", test.files, gen.outputFiles)
Colin Cross1a527682019-09-23 15:55:30 -0700626 })
627 }
Colin Cross2a076922018-10-04 23:28:25 -0700628}
629
Vinh Tran140d5882022-06-10 14:23:27 -0400630func TestGensrcsBuildBrokenDepfile(t *testing.T) {
631 tests := []struct {
632 name string
633 prop string
634 BuildBrokenDepfile *bool
635 err string
636 }{
637 {
638 name: `error when BuildBrokenDepfile is set to false`,
639 prop: `
640 depfile: true,
641 cmd: "cat $(in) > $(out) && cat $(depfile)",
642 `,
643 BuildBrokenDepfile: proptools.BoolPtr(false),
644 err: "depfile: Deprecated to ensure the module type is convertible to Bazel",
645 },
646 {
647 name: `error when BuildBrokenDepfile is not set`,
648 prop: `
649 depfile: true,
650 cmd: "cat $(in) > $(out) && cat $(depfile)",
651 `,
652 err: "depfile: Deprecated to ensure the module type is convertible to Bazel.",
653 },
654 {
655 name: `no error when BuildBrokenDepfile is explicitly set to true`,
656 prop: `
657 depfile: true,
658 cmd: "cat $(in) > $(out) && cat $(depfile)",
659 `,
660 BuildBrokenDepfile: proptools.BoolPtr(true),
661 },
662 {
663 name: `no error if depfile is not set`,
664 prop: `
665 cmd: "cat $(in) > $(out)",
666 `,
667 },
668 }
669 for _, test := range tests {
670 t.Run(test.name, func(t *testing.T) {
671 bp := fmt.Sprintf(`
672 gensrcs {
673 name: "foo",
674 srcs: ["data.txt"],
675 %s
676 }`, test.prop)
677
678 var expectedErrors []string
679 if test.err != "" {
680 expectedErrors = append(expectedErrors, test.err)
681 }
682 android.GroupFixturePreparers(
683 prepareForGenRuleTest,
684 android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
685 if test.BuildBrokenDepfile != nil {
686 variables.BuildBrokenDepfile = test.BuildBrokenDepfile
687 }
688 }),
689 ).
690 ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
691 RunTestWithBp(t, bp)
692 })
693
694 }
695}
696
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800697func TestGenruleDefaults(t *testing.T) {
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800698 bp := `
699 genrule_defaults {
700 name: "gen_defaults1",
701 cmd: "cp $(in) $(out)",
702 }
703
704 genrule_defaults {
705 name: "gen_defaults2",
706 srcs: ["in1"],
707 }
708
709 genrule {
710 name: "gen",
711 out: ["out"],
712 defaults: ["gen_defaults1", "gen_defaults2"],
713 }
714 `
Paul Duffin672cb9f2021-03-03 02:30:37 +0000715
Paul Duffin89648f92021-03-20 00:36:55 +0000716 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
Paul Duffin672cb9f2021-03-03 02:30:37 +0000717
718 gen := result.Module("gen", "").(*Module)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800719
Colin Crosse16ce362020-11-12 08:29:30 -0800720 expectedCmd := "cp in1 __SBOX_SANDBOX_DIR__/out/out"
Paul Duffine84b1332021-03-12 11:59:43 +0000721 android.AssertStringEquals(t, "cmd", expectedCmd, gen.rawCommands[0])
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800722
723 expectedSrcs := []string{"in1"}
Paul Duffine84b1332021-03-12 11:59:43 +0000724 android.AssertDeepEquals(t, "srcs", expectedSrcs, gen.properties.Srcs)
Jaewoong Jung98716bd2018-12-10 08:13:18 -0800725}
726
Colin Crossfa65cee2021-03-22 17:05:59 -0700727func TestGenruleAllowMissingDependencies(t *testing.T) {
728 bp := `
729 output {
730 name: "disabled",
731 enabled: false,
732 }
733
734 genrule {
735 name: "gen",
736 srcs: [
737 ":disabled",
738 ],
739 out: ["out"],
740 cmd: "cat $(in) > $(out)",
741 }
742 `
Paul Duffin79abe572021-03-29 02:16:14 +0100743 result := android.GroupFixturePreparers(
744 prepareForGenRuleTest,
Colin Crossfa65cee2021-03-22 17:05:59 -0700745 android.FixtureModifyConfigAndContext(
746 func(config android.Config, ctx *android.TestContext) {
747 config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
748 ctx.SetAllowMissingDependencies(true)
749 })).RunTestWithBp(t, bp)
750
751 gen := result.ModuleForTests("gen", "").Output("out")
752 if gen.Rule != android.ErrorRule {
753 t.Errorf("Expected missing dependency error rule for gen, got %q", gen.Rule.String())
754 }
755}
756
Jooyung Han8c7e3ed2021-06-28 17:35:58 +0900757func TestGenruleOutputFiles(t *testing.T) {
758 bp := `
759 genrule {
760 name: "gen",
761 out: ["foo", "sub/bar"],
762 cmd: "echo foo > $(location foo) && echo bar > $(location sub/bar)",
763 }
764 use_source {
765 name: "gen_foo",
766 srcs: [":gen{foo}"],
767 }
768 use_source {
769 name: "gen_bar",
770 srcs: [":gen{sub/bar}"],
771 }
772 use_source {
773 name: "gen_all",
774 srcs: [":gen"],
775 }
776 `
777
778 result := prepareForGenRuleTest.RunTestWithBp(t, testGenruleBp()+bp)
779 android.AssertPathsRelativeToTopEquals(t,
780 "genrule.tag with output",
781 []string{"out/soong/.intermediates/gen/gen/foo"},
782 result.ModuleForTests("gen_foo", "").Module().(*useSource).srcs)
783 android.AssertPathsRelativeToTopEquals(t,
784 "genrule.tag with output in subdir",
785 []string{"out/soong/.intermediates/gen/gen/sub/bar"},
786 result.ModuleForTests("gen_bar", "").Module().(*useSource).srcs)
787 android.AssertPathsRelativeToTopEquals(t,
788 "genrule.tag with all",
789 []string{"out/soong/.intermediates/gen/gen/foo", "out/soong/.intermediates/gen/gen/sub/bar"},
790 result.ModuleForTests("gen_all", "").Module().(*useSource).srcs)
791}
792
Vinh Tran370e08c2022-09-23 18:09:01 -0400793func TestGenSrcsWithNonRootAndroidBpOutputFiles(t *testing.T) {
794 result := android.GroupFixturePreparers(
795 prepareForGenRuleTest,
796 android.FixtureMergeMockFs(android.MockFS{
797 "external-protos/path/Android.bp": []byte(`
798 filegroup {
799 name: "external-protos",
800 srcs: ["baz/baz.proto", "bar.proto"],
801 }
802 `),
803 "package-dir/Android.bp": []byte(`
804 gensrcs {
805 name: "module-name",
806 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
807 srcs: [
808 "src/foo.proto",
809 ":external-protos",
810 ],
811 output_extension: "proto.h",
812 }
813 `),
814 }),
815 ).RunTest(t)
816
817 exportedIncludeDir := "out/soong/.intermediates/package-dir/module-name/gen/gensrcs"
818 gen := result.Module("module-name", "").(*Module)
819
820 android.AssertPathsRelativeToTopEquals(
821 t,
822 "include path",
823 []string{exportedIncludeDir},
824 gen.exportedIncludeDirs,
825 )
826 android.AssertPathsRelativeToTopEquals(
827 t,
828 "files",
829 []string{
830 exportedIncludeDir + "/package-dir/src/foo.proto.h",
831 exportedIncludeDir + "/external-protos/path/baz/baz.proto.h",
832 exportedIncludeDir + "/external-protos/path/bar.proto.h",
833 },
834 gen.outputFiles,
835 )
836}
837
838func TestGenSrcsWithSrcsFromExternalPackage(t *testing.T) {
839 bp := `
840 gensrcs {
841 name: "module-name",
842 cmd: "mkdir -p $(genDir) && cat $(in) >> $(genDir)/$(out)",
843 srcs: [
844 ":external-protos",
845 ],
846 output_extension: "proto.h",
847 }
848 `
849 result := android.GroupFixturePreparers(
850 prepareForGenRuleTest,
851 android.FixtureMergeMockFs(android.MockFS{
852 "external-protos/path/Android.bp": []byte(`
853 filegroup {
854 name: "external-protos",
855 srcs: ["foo/foo.proto", "bar.proto"],
856 }
857 `),
858 }),
859 ).RunTestWithBp(t, bp)
860
861 exportedIncludeDir := "out/soong/.intermediates/module-name/gen/gensrcs"
862 gen := result.Module("module-name", "").(*Module)
863
864 android.AssertPathsRelativeToTopEquals(
865 t,
866 "include path",
867 []string{exportedIncludeDir},
868 gen.exportedIncludeDirs,
869 )
870 android.AssertPathsRelativeToTopEquals(
871 t,
872 "files",
873 []string{
874 exportedIncludeDir + "/external-protos/path/foo/foo.proto.h",
875 exportedIncludeDir + "/external-protos/path/bar.proto.h",
876 },
877 gen.outputFiles,
878 )
879}
880
Martin Stjernholmdbd814d2022-01-12 23:18:30 +0000881func TestPrebuiltTool(t *testing.T) {
882 testcases := []struct {
883 name string
884 bp string
885 expectedToolName string
886 }{
887 {
888 name: "source only",
889 bp: `
890 tool { name: "tool" }
891 `,
892 expectedToolName: "bin/tool",
893 },
894 {
895 name: "prebuilt only",
896 bp: `
897 prebuilt_tool { name: "tool" }
898 `,
899 expectedToolName: "prebuilt_bin/tool",
900 },
901 {
902 name: "source preferred",
903 bp: `
904 tool { name: "tool" }
905 prebuilt_tool { name: "tool" }
906 `,
907 expectedToolName: "bin/tool",
908 },
909 {
910 name: "prebuilt preferred",
911 bp: `
912 tool { name: "tool" }
913 prebuilt_tool { name: "tool", prefer: true }
914 `,
915 expectedToolName: "prebuilt_bin/prebuilt_tool",
916 },
917 {
918 name: "source disabled",
919 bp: `
920 tool { name: "tool", enabled: false }
921 prebuilt_tool { name: "tool" }
922 `,
923 expectedToolName: "prebuilt_bin/prebuilt_tool",
924 },
925 }
926
927 for _, test := range testcases {
928 t.Run(test.name, func(t *testing.T) {
929 result := prepareForGenRuleTest.RunTestWithBp(t, test.bp+`
930 genrule {
931 name: "gen",
932 tools: ["tool"],
933 out: ["foo"],
934 cmd: "$(location tool)",
935 }
936 `)
937 gen := result.Module("gen", "").(*Module)
938 expectedCmd := "__SBOX_SANDBOX_DIR__/tools/out/" + test.expectedToolName
939 android.AssertStringEquals(t, "command", expectedCmd, gen.rawCommands[0])
940 })
941 }
942}
943
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400944func TestGenruleWithBazel(t *testing.T) {
945 bp := `
946 genrule {
947 name: "foo",
948 out: ["one.txt", "two.txt"],
Chris Parsonsaa8be052020-10-14 16:22:37 -0400949 bazel_module: { label: "//foo/bar:bar" },
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400950 }
951 `
952
Paul Duffin89648f92021-03-20 00:36:55 +0000953 result := android.GroupFixturePreparers(
954 prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
955 config.BazelContext = android.MockBazelContext{
Liz Kammera92e8442021-04-07 20:25:21 -0400956 OutputBaseDir: "outputbase",
957 LabelToOutputFiles: map[string][]string{
Paul Duffin89648f92021-03-20 00:36:55 +0000958 "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
959 })).RunTestWithBp(t, testGenruleBp()+bp)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400960
Paul Duffin672cb9f2021-03-03 02:30:37 +0000961 gen := result.Module("foo", "").(*Module)
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400962
Chris Parsonsdbcb1ff2020-12-10 17:19:18 -0500963 expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
964 "outputbase/execroot/__main__/bazeltwo.txt"}
Paul Duffine84b1332021-03-12 11:59:43 +0000965 android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
966 android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400967}
968
Jihoon Kangc170af42022-08-20 05:26:38 +0000969func TestGenruleWithGlobPaths(t *testing.T) {
970 testcases := []struct {
971 name string
972 bp string
973 additionalFiles android.MockFS
974 expectedCmd string
975 }{
976 {
977 name: "single file in directory with $ sign",
978 bp: `
979 genrule {
980 name: "gen",
981 srcs: ["inn*.txt"],
982 out: ["out.txt"],
983 cmd: "cp $(in) $(out)",
984 }
985 `,
986 additionalFiles: android.MockFS{"inn$1.txt": nil},
987 expectedCmd: "cp 'inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
988 },
989 {
990 name: "multiple file in directory with $ sign",
991 bp: `
992 genrule {
993 name: "gen",
994 srcs: ["inn*.txt"],
995 out: ["."],
996 cmd: "cp $(in) $(out)",
997 }
998 `,
999 additionalFiles: android.MockFS{"inn$1.txt": nil, "inn$2.txt": nil},
1000 expectedCmd: "cp 'inn$1.txt' 'inn$2.txt' __SBOX_SANDBOX_DIR__/out",
1001 },
1002 {
1003 name: "file in directory with other shell unsafe character",
1004 bp: `
1005 genrule {
1006 name: "gen",
1007 srcs: ["inn*.txt"],
1008 out: ["out.txt"],
1009 cmd: "cp $(in) $(out)",
1010 }
1011 `,
1012 additionalFiles: android.MockFS{"inn@1.txt": nil},
1013 expectedCmd: "cp 'inn@1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1014 },
1015 {
1016 name: "glob location param with filepath containing $",
1017 bp: `
1018 genrule {
1019 name: "gen",
1020 srcs: ["**/inn*"],
1021 out: ["."],
1022 cmd: "cp $(in) $(location **/inn*)",
1023 }
1024 `,
1025 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1026 expectedCmd: "cp 'a/inn$1.txt' 'a/inn$1.txt'",
1027 },
1028 {
1029 name: "glob locations param with filepath containing $",
1030 bp: `
1031 genrule {
1032 name: "gen",
1033 tool_files: ["**/inn*"],
1034 out: ["out.txt"],
1035 cmd: "cp $(locations **/inn*) $(out)",
1036 }
1037 `,
1038 additionalFiles: android.MockFS{"a/inn$1.txt": nil},
1039 expectedCmd: "cp '__SBOX_SANDBOX_DIR__/tools/src/a/inn$1.txt' __SBOX_SANDBOX_DIR__/out/out.txt",
1040 },
1041 }
1042
1043 for _, test := range testcases {
1044 t.Run(test.name, func(t *testing.T) {
1045 result := android.GroupFixturePreparers(
1046 prepareForGenRuleTest,
1047 android.FixtureMergeMockFs(test.additionalFiles),
1048 ).RunTestWithBp(t, test.bp)
1049 gen := result.Module("gen", "").(*Module)
1050 android.AssertStringEquals(t, "command", test.expectedCmd, gen.rawCommands[0])
1051 })
1052 }
1053}
1054
Colin Cross2a076922018-10-04 23:28:25 -07001055type testTool struct {
1056 android.ModuleBase
1057 outputFile android.Path
1058}
1059
1060func toolFactory() android.Module {
1061 module := &testTool{}
1062 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1063 return module
1064}
1065
Colin Cross2a076922018-10-04 23:28:25 -07001066func (t *testTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Crossba9e4032020-11-24 16:32:22 -08001067 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
Colin Cross2a076922018-10-04 23:28:25 -07001068}
1069
1070func (t *testTool) HostToolPath() android.OptionalPath {
1071 return android.OptionalPathForPath(t.outputFile)
1072}
1073
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001074type prebuiltTestTool struct {
1075 android.ModuleBase
1076 prebuilt android.Prebuilt
1077 testTool
1078}
1079
1080func (p *prebuiltTestTool) Name() string {
1081 return p.prebuilt.Name(p.ModuleBase.Name())
1082}
1083
1084func (p *prebuiltTestTool) Prebuilt() *android.Prebuilt {
1085 return &p.prebuilt
1086}
1087
1088func (t *prebuiltTestTool) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1089 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "prebuilt_bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1090}
1091
1092func prebuiltToolFactory() android.Module {
1093 module := &prebuiltTestTool{}
1094 android.InitPrebuiltModuleWithoutSrcs(module)
1095 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1096 return module
1097}
1098
Colin Crossfe17f6f2019-03-28 19:30:56 -07001099var _ android.HostToolProvider = (*testTool)(nil)
Martin Stjernholmdbd814d2022-01-12 23:18:30 +00001100var _ android.HostToolProvider = (*prebuiltTestTool)(nil)
Colin Crossfa65cee2021-03-22 17:05:59 -07001101
1102type testOutputProducer struct {
1103 android.ModuleBase
1104 outputFile android.Path
1105}
1106
1107func outputProducerFactory() android.Module {
1108 module := &testOutputProducer{}
1109 android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
1110 return module
1111}
1112
1113func (t *testOutputProducer) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1114 t.outputFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "bin"), ctx.ModuleName(), android.PathForOutput(ctx, ctx.ModuleName()))
1115}
1116
1117func (t *testOutputProducer) OutputFiles(tag string) (android.Paths, error) {
1118 return android.Paths{t.outputFile}, nil
1119}
1120
1121var _ android.OutputFileProducer = (*testOutputProducer)(nil)
Jooyung Han8c7e3ed2021-06-28 17:35:58 +09001122
1123type useSource struct {
1124 android.ModuleBase
1125 props struct {
1126 Srcs []string `android:"path"`
1127 }
1128 srcs android.Paths
1129}
1130
1131func (s *useSource) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1132 s.srcs = android.PathsForModuleSrc(ctx, s.props.Srcs)
1133}
1134
1135func useSourceFactory() android.Module {
1136 module := &useSource{}
1137 module.AddProperties(&module.props)
1138 android.InitAndroidModule(module)
1139 return module
1140}