• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2021 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 bp2build
16
17import (
18	"fmt"
19	"testing"
20
21	"android/soong/android"
22	"android/soong/cc"
23	"android/soong/genrule"
24	"android/soong/java"
25)
26
27func registerGenruleModuleTypes(ctx android.RegistrationContext) {
28	ctx.RegisterModuleType("genrule_defaults", func() android.Module { return genrule.DefaultsFactory() })
29}
30
31func runGenruleTestCase(t *testing.T, tc Bp2buildTestCase) {
32	t.Helper()
33	(&tc).ModuleTypeUnderTest = "genrule"
34	(&tc).ModuleTypeUnderTestFactory = genrule.GenRuleFactory
35	RunBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
36}
37
38func otherGenruleBp(genruleTarget string) map[string]string {
39	return map[string]string{
40		"other/Android.bp": fmt.Sprintf(`%s {
41    name: "foo.tool",
42    out: ["foo_tool.out"],
43    srcs: ["foo_tool.in"],
44    cmd: "cp $(in) $(out)",
45}
46%s {
47    name: "other.tool",
48    out: ["other_tool.out"],
49    srcs: ["other_tool.in"],
50    cmd: "cp $(in) $(out)",
51}`, genruleTarget, genruleTarget),
52	}
53}
54
55func TestGenruleCliVariableReplacement(t *testing.T) {
56	testCases := []struct {
57		moduleType string
58		factory    android.ModuleFactory
59		genDir     string
60		hod        android.HostOrDeviceSupported
61	}{
62		{
63			moduleType: "genrule",
64			factory:    genrule.GenRuleFactory,
65			genDir:     "$(RULEDIR)",
66		},
67		{
68			moduleType: "cc_genrule",
69			factory:    cc.GenRuleFactory,
70			genDir:     "$(RULEDIR)",
71			hod:        android.DeviceSupported,
72		},
73		{
74			moduleType: "java_genrule",
75			factory:    java.GenRuleFactory,
76			genDir:     "$(RULEDIR)",
77			hod:        android.DeviceSupported,
78		},
79		{
80			moduleType: "java_genrule_host",
81			factory:    java.GenRuleFactoryHost,
82			genDir:     "$(RULEDIR)",
83			hod:        android.HostSupported,
84		},
85	}
86
87	bp := `%s {
88    name: "foo.tool",
89    out: ["foo_tool.out"],
90    srcs: ["foo_tool.in"],
91    cmd: "cp $(in) $(out)",
92    bazel_module: { bp2build_available: false },
93}
94
95%s {
96    name: "foo",
97    out: ["foo.out"],
98    srcs: ["foo.in"],
99    tools: [":foo.tool"],
100    cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
101    bazel_module: { bp2build_available: true },
102}`
103
104	for _, tc := range testCases {
105		moduleAttrs := AttrNameToString{
106			"cmd":   fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
107			"outs":  `["foo.out"]`,
108			"srcs":  `["foo.in"]`,
109			"tools": `[":foo.tool"]`,
110		}
111
112		expectedBazelTargets := []string{
113			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
114		}
115
116		t.Run(tc.moduleType, func(t *testing.T) {
117			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
118				Bp2buildTestCase{
119					ModuleTypeUnderTest:        tc.moduleType,
120					ModuleTypeUnderTestFactory: tc.factory,
121					Blueprint:                  fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
122					ExpectedBazelTargets:       expectedBazelTargets,
123				})
124		})
125	}
126}
127
128func TestGenruleLocationsLabel(t *testing.T) {
129	testCases := []struct {
130		moduleType string
131		factory    android.ModuleFactory
132		hod        android.HostOrDeviceSupported
133	}{
134		{
135			moduleType: "genrule",
136			factory:    genrule.GenRuleFactory,
137		},
138		{
139			moduleType: "cc_genrule",
140			factory:    cc.GenRuleFactory,
141			hod:        android.DeviceSupported,
142		},
143		{
144			moduleType: "java_genrule",
145			factory:    java.GenRuleFactory,
146			hod:        android.DeviceSupported,
147		},
148		{
149			moduleType: "java_genrule_host",
150			factory:    java.GenRuleFactoryHost,
151			hod:        android.HostSupported,
152		},
153	}
154
155	bp := `%s {
156    name: "foo.tools",
157    out: ["foo_tool.out", "foo_tool2.out"],
158    srcs: ["foo_tool.in"],
159    cmd: "cp $(in) $(out)",
160    bazel_module: { bp2build_available: true },
161}
162
163%s {
164    name: "foo",
165    out: ["foo.out"],
166    srcs: ["foo.in"],
167    tools: [":foo.tools"],
168    cmd: "$(locations :foo.tools) -s $(out) $(in)",
169    bazel_module: { bp2build_available: true },
170}`
171
172	for _, tc := range testCases {
173		fooAttrs := AttrNameToString{
174			"cmd":   `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
175			"outs":  `["foo.out"]`,
176			"srcs":  `["foo.in"]`,
177			"tools": `[":foo.tools"]`,
178		}
179		fooToolsAttrs := AttrNameToString{
180			"cmd": `"cp $(SRCS) $(OUTS)"`,
181			"outs": `[
182        "foo_tool.out",
183        "foo_tool2.out",
184    ]`,
185			"srcs": `["foo_tool.in"]`,
186		}
187
188		expectedBazelTargets := []string{
189			makeBazelTargetHostOrDevice("genrule", "foo", fooAttrs, tc.hod),
190			makeBazelTargetHostOrDevice("genrule", "foo.tools", fooToolsAttrs, tc.hod),
191		}
192
193		t.Run(tc.moduleType, func(t *testing.T) {
194			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
195				Bp2buildTestCase{
196					ModuleTypeUnderTest:        tc.moduleType,
197					ModuleTypeUnderTestFactory: tc.factory,
198					Blueprint:                  fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
199					ExpectedBazelTargets:       expectedBazelTargets,
200				})
201		})
202	}
203}
204
205func TestGenruleLocationsAbsoluteLabel(t *testing.T) {
206	testCases := []struct {
207		moduleType string
208		factory    android.ModuleFactory
209		hod        android.HostOrDeviceSupported
210	}{
211		{
212			moduleType: "genrule",
213			factory:    genrule.GenRuleFactory,
214		},
215		{
216			moduleType: "cc_genrule",
217			factory:    cc.GenRuleFactory,
218			hod:        android.DeviceSupported,
219		},
220		{
221			moduleType: "java_genrule",
222			factory:    java.GenRuleFactory,
223			hod:        android.DeviceSupported,
224		},
225		{
226			moduleType: "java_genrule_host",
227			factory:    java.GenRuleFactoryHost,
228			hod:        android.HostSupported,
229		},
230	}
231
232	bp := `%s {
233    name: "foo",
234    out: ["foo.out"],
235    srcs: ["foo.in"],
236    tool_files: [":foo.tool"],
237    cmd: "$(locations :foo.tool) -s $(out) $(in)",
238    bazel_module: { bp2build_available: true },
239}`
240
241	for _, tc := range testCases {
242		moduleAttrs := AttrNameToString{
243			"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
244			"outs":  `["foo.out"]`,
245			"srcs":  `["foo.in"]`,
246			"tools": `["//other:foo.tool"]`,
247		}
248
249		expectedBazelTargets := []string{
250			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
251		}
252
253		t.Run(tc.moduleType, func(t *testing.T) {
254			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
255				Bp2buildTestCase{
256					ModuleTypeUnderTest:        tc.moduleType,
257					ModuleTypeUnderTestFactory: tc.factory,
258					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
259					ExpectedBazelTargets:       expectedBazelTargets,
260					Filesystem:                 otherGenruleBp(tc.moduleType),
261				})
262		})
263	}
264}
265
266func TestGenruleSrcsLocationsAbsoluteLabel(t *testing.T) {
267	testCases := []struct {
268		moduleType string
269		factory    android.ModuleFactory
270		hod        android.HostOrDeviceSupported
271	}{
272		{
273			moduleType: "genrule",
274			factory:    genrule.GenRuleFactory,
275		},
276		{
277			moduleType: "cc_genrule",
278			factory:    cc.GenRuleFactory,
279			hod:        android.DeviceSupported,
280		},
281		{
282			moduleType: "java_genrule",
283			factory:    java.GenRuleFactory,
284			hod:        android.DeviceSupported,
285		},
286		{
287			moduleType: "java_genrule_host",
288			factory:    java.GenRuleFactoryHost,
289			hod:        android.HostSupported,
290		},
291	}
292
293	bp := `%s {
294    name: "foo",
295    out: ["foo.out"],
296    srcs: [":other.tool"],
297    tool_files: [":foo.tool"],
298    cmd: "$(locations :foo.tool) -s $(out) $(location :other.tool)",
299    bazel_module: { bp2build_available: true },
300}`
301
302	for _, tc := range testCases {
303		moduleAttrs := AttrNameToString{
304			"cmd":   `"$(locations //other:foo.tool) -s $(OUTS) $(location //other:other.tool)"`,
305			"outs":  `["foo.out"]`,
306			"srcs":  `["//other:other.tool"]`,
307			"tools": `["//other:foo.tool"]`,
308		}
309
310		expectedBazelTargets := []string{
311			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
312		}
313
314		t.Run(tc.moduleType, func(t *testing.T) {
315			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
316				Bp2buildTestCase{
317					ModuleTypeUnderTest:        tc.moduleType,
318					ModuleTypeUnderTestFactory: tc.factory,
319					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
320					ExpectedBazelTargets:       expectedBazelTargets,
321					Filesystem:                 otherGenruleBp(tc.moduleType),
322				})
323		})
324	}
325}
326
327func TestGenruleLocationLabelShouldSubstituteFirstToolLabel(t *testing.T) {
328	testCases := []struct {
329		moduleType string
330		factory    android.ModuleFactory
331		hod        android.HostOrDeviceSupported
332	}{
333		{
334			moduleType: "genrule",
335			factory:    genrule.GenRuleFactory,
336		},
337		{
338			moduleType: "cc_genrule",
339			factory:    cc.GenRuleFactory,
340			hod:        android.DeviceSupported,
341		},
342		{
343			moduleType: "java_genrule",
344			factory:    java.GenRuleFactory,
345			hod:        android.DeviceSupported,
346		},
347		{
348			moduleType: "java_genrule_host",
349			factory:    java.GenRuleFactoryHost,
350			hod:        android.HostSupported,
351		},
352	}
353
354	bp := `%s {
355    name: "foo",
356    out: ["foo.out"],
357    srcs: ["foo.in"],
358    tool_files: [":foo.tool", ":other.tool"],
359    cmd: "$(location) -s $(out) $(in)",
360    bazel_module: { bp2build_available: true },
361}`
362
363	for _, tc := range testCases {
364		moduleAttrs := AttrNameToString{
365			"cmd":  `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
366			"outs": `["foo.out"]`,
367			"srcs": `["foo.in"]`,
368			"tools": `[
369        "//other:foo.tool",
370        "//other:other.tool",
371    ]`,
372		}
373
374		expectedBazelTargets := []string{
375			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
376		}
377
378		t.Run(tc.moduleType, func(t *testing.T) {
379			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
380				Bp2buildTestCase{
381					ModuleTypeUnderTest:        tc.moduleType,
382					ModuleTypeUnderTestFactory: tc.factory,
383					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
384					ExpectedBazelTargets:       expectedBazelTargets,
385					Filesystem:                 otherGenruleBp(tc.moduleType),
386				})
387		})
388	}
389}
390
391func TestGenruleLocationsLabelShouldSubstituteFirstToolLabel(t *testing.T) {
392	testCases := []struct {
393		moduleType string
394		factory    android.ModuleFactory
395		hod        android.HostOrDeviceSupported
396	}{
397		{
398			moduleType: "genrule",
399			factory:    genrule.GenRuleFactory,
400		},
401		{
402			moduleType: "cc_genrule",
403			factory:    cc.GenRuleFactory,
404			hod:        android.DeviceSupported,
405		},
406		{
407			moduleType: "java_genrule",
408			factory:    java.GenRuleFactory,
409			hod:        android.DeviceSupported,
410		},
411		{
412			moduleType: "java_genrule_host",
413			factory:    java.GenRuleFactoryHost,
414			hod:        android.HostSupported,
415		},
416	}
417
418	bp := `%s {
419    name: "foo",
420    out: ["foo.out"],
421    srcs: ["foo.in"],
422    tool_files: [":foo.tool", ":other.tool"],
423    cmd: "$(locations) -s $(out) $(in)",
424    bazel_module: { bp2build_available: true },
425}`
426
427	for _, tc := range testCases {
428		moduleAttrs := AttrNameToString{
429			"cmd":  `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
430			"outs": `["foo.out"]`,
431			"srcs": `["foo.in"]`,
432			"tools": `[
433        "//other:foo.tool",
434        "//other:other.tool",
435    ]`,
436		}
437
438		expectedBazelTargets := []string{
439			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
440		}
441
442		t.Run(tc.moduleType, func(t *testing.T) {
443			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
444				Bp2buildTestCase{
445					ModuleTypeUnderTest:        tc.moduleType,
446					ModuleTypeUnderTestFactory: tc.factory,
447					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
448					ExpectedBazelTargets:       expectedBazelTargets,
449					Filesystem:                 otherGenruleBp(tc.moduleType),
450				})
451		})
452	}
453}
454
455func TestGenruleWithoutToolsOrToolFiles(t *testing.T) {
456	testCases := []struct {
457		moduleType string
458		factory    android.ModuleFactory
459		hod        android.HostOrDeviceSupported
460	}{
461		{
462			moduleType: "genrule",
463			factory:    genrule.GenRuleFactory,
464		},
465		{
466			moduleType: "cc_genrule",
467			factory:    cc.GenRuleFactory,
468			hod:        android.DeviceSupported,
469		},
470		{
471			moduleType: "java_genrule",
472			factory:    java.GenRuleFactory,
473			hod:        android.DeviceSupported,
474		},
475		{
476			moduleType: "java_genrule_host",
477			factory:    java.GenRuleFactoryHost,
478			hod:        android.HostSupported,
479		},
480	}
481
482	bp := `%s {
483    name: "foo",
484    out: ["foo.out"],
485    srcs: ["foo.in"],
486    cmd: "cp $(in) $(out)",
487    bazel_module: { bp2build_available: true },
488}`
489
490	for _, tc := range testCases {
491		moduleAttrs := AttrNameToString{
492			"cmd":  `"cp $(SRCS) $(OUTS)"`,
493			"outs": `["foo.out"]`,
494			"srcs": `["foo.in"]`,
495		}
496
497		expectedBazelTargets := []string{
498			makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
499		}
500
501		t.Run(tc.moduleType, func(t *testing.T) {
502			RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
503				Bp2buildTestCase{
504					ModuleTypeUnderTest:        tc.moduleType,
505					ModuleTypeUnderTestFactory: tc.factory,
506					Blueprint:                  fmt.Sprintf(bp, tc.moduleType),
507					ExpectedBazelTargets:       expectedBazelTargets,
508				})
509		})
510	}
511}
512
513func TestGenruleBp2BuildInlinesDefaults(t *testing.T) {
514	testCases := []Bp2buildTestCase{
515		{
516			Description: "genrule applies properties from a genrule_defaults dependency if not specified",
517			Blueprint: `genrule_defaults {
518    name: "gen_defaults",
519    cmd: "do-something $(in) $(out)",
520}
521genrule {
522    name: "gen",
523    out: ["out"],
524    srcs: ["in1"],
525    defaults: ["gen_defaults"],
526    bazel_module: { bp2build_available: true },
527}
528`,
529			ExpectedBazelTargets: []string{
530				MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
531					"cmd":  `"do-something $(SRCS) $(OUTS)"`,
532					"outs": `["out"]`,
533					"srcs": `["in1"]`,
534				}),
535			},
536		},
537		{
538			Description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
539			Blueprint: `genrule_defaults {
540    name: "gen_defaults",
541    out: ["out-from-defaults"],
542    srcs: ["in-from-defaults"],
543    cmd: "cmd-from-defaults",
544}
545genrule {
546    name: "gen",
547    out: ["out"],
548    srcs: ["in1"],
549    defaults: ["gen_defaults"],
550    cmd: "do-something $(in) $(out)",
551    bazel_module: { bp2build_available: true },
552}
553`,
554			ExpectedBazelTargets: []string{
555				MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
556					"cmd": `"do-something $(SRCS) $(OUTS)"`,
557					"outs": `[
558        "out-from-defaults",
559        "out",
560    ]`,
561					"srcs": `[
562        "in-from-defaults",
563        "in1",
564    ]`,
565				}),
566			},
567		},
568		{
569			Description: "genrule applies properties from list of genrule_defaults",
570			Blueprint: `genrule_defaults {
571    name: "gen_defaults1",
572    cmd: "cp $(in) $(out)",
573}
574
575genrule_defaults {
576    name: "gen_defaults2",
577    srcs: ["in1"],
578}
579
580genrule {
581    name: "gen",
582    out: ["out"],
583    defaults: ["gen_defaults1", "gen_defaults2"],
584    bazel_module: { bp2build_available: true },
585}
586`,
587			ExpectedBazelTargets: []string{
588				MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
589					"cmd":  `"cp $(SRCS) $(OUTS)"`,
590					"outs": `["out"]`,
591					"srcs": `["in1"]`,
592				}),
593			},
594		},
595		{
596			Description: "genrule applies properties from genrule_defaults transitively",
597			Blueprint: `genrule_defaults {
598    name: "gen_defaults1",
599    defaults: ["gen_defaults2"],
600    cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
601}
602
603genrule_defaults {
604    name: "gen_defaults2",
605    defaults: ["gen_defaults3"],
606    cmd: "cmd2 $(in) $(out)",
607    out: ["out-from-2"],
608    srcs: ["in1"],
609}
610
611genrule_defaults {
612    name: "gen_defaults3",
613    out: ["out-from-3"],
614    srcs: ["srcs-from-3"],
615}
616
617genrule {
618    name: "gen",
619    out: ["out"],
620    defaults: ["gen_defaults1"],
621    bazel_module: { bp2build_available: true },
622}
623`,
624			ExpectedBazelTargets: []string{
625				MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
626					"cmd": `"cmd1 $(SRCS) $(OUTS)"`,
627					"outs": `[
628        "out-from-3",
629        "out-from-2",
630        "out",
631    ]`,
632					"srcs": `[
633        "srcs-from-3",
634        "in1",
635    ]`,
636				}),
637			},
638		},
639	}
640
641	for _, testCase := range testCases {
642		t.Run(testCase.Description, func(t *testing.T) {
643			runGenruleTestCase(t, testCase)
644		})
645	}
646}
647
648func TestCcGenruleArchAndExcludeSrcs(t *testing.T) {
649	name := "cc_genrule with arch"
650	bp := `
651	cc_genrule {
652		name: "foo",
653		srcs: [
654			"foo1.in",
655			"foo2.in",
656		],
657		exclude_srcs: ["foo2.in"],
658		arch: {
659			arm: {
660				srcs: [
661					"foo1_arch.in",
662					"foo2_arch.in",
663				],
664				exclude_srcs: ["foo2_arch.in"],
665			},
666		},
667		cmd: "cat $(in) > $(out)",
668		bazel_module: { bp2build_available: true },
669	}`
670
671	expectedBazelAttrs := AttrNameToString{
672		"srcs": `["foo1.in"] + select({
673        "//build/bazel/platforms/arch:arm": ["foo1_arch.in"],
674        "//conditions:default": [],
675    })`,
676		"cmd":                    `"cat $(SRCS) > $(OUTS)"`,
677		"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
678	}
679
680	expectedBazelTargets := []string{
681		MakeBazelTargetNoRestrictions("genrule", "foo", expectedBazelAttrs),
682	}
683
684	t.Run(name, func(t *testing.T) {
685		RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
686			Bp2buildTestCase{
687				ModuleTypeUnderTest:        "cc_genrule",
688				ModuleTypeUnderTestFactory: cc.GenRuleFactory,
689				Blueprint:                  bp,
690				ExpectedBazelTargets:       expectedBazelTargets,
691			})
692	})
693}
694