1package bp2build
2
3import (
4	"android/soong/android"
5	"android/soong/bazel"
6)
7
8var (
9	// A default configuration for tests to not have to specify bp2build_available on top level targets.
10	bp2buildConfig = android.Bp2BuildConfig{
11		android.BP2BUILD_TOPLEVEL: android.Bp2BuildDefaultTrueRecursively,
12	}
13)
14
15type nestedProps struct {
16	Nested_prop string
17}
18
19type customProps struct {
20	Bool_prop     bool
21	Bool_ptr_prop *bool
22	// Ensure that properties tagged `blueprint:mutated` are omitted
23	Int_prop         int `blueprint:"mutated"`
24	Int64_ptr_prop   *int64
25	String_prop      string
26	String_ptr_prop  *string
27	String_list_prop []string
28
29	Nested_props     nestedProps
30	Nested_props_ptr *nestedProps
31
32	Arch_paths []string `android:"path,arch_variant"`
33}
34
35type customModule struct {
36	android.ModuleBase
37	android.BazelModuleBase
38
39	props customProps
40}
41
42// OutputFiles is needed because some instances of this module use dist with a
43// tag property which requires the module implements OutputFileProducer.
44func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
45	return android.PathsForTesting("path" + tag), nil
46}
47
48func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
49	// nothing for now.
50}
51
52func customModuleFactoryBase() android.Module {
53	module := &customModule{}
54	module.AddProperties(&module.props)
55	android.InitBazelModule(module)
56	return module
57}
58
59func customModuleFactory() android.Module {
60	m := customModuleFactoryBase()
61	android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
62	return m
63}
64
65type testProps struct {
66	Test_prop struct {
67		Test_string_prop string
68	}
69}
70
71type customTestModule struct {
72	android.ModuleBase
73
74	props      customProps
75	test_props testProps
76}
77
78func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
79	// nothing for now.
80}
81
82func customTestModuleFactoryBase() android.Module {
83	m := &customTestModule{}
84	m.AddProperties(&m.props)
85	m.AddProperties(&m.test_props)
86	return m
87}
88
89func customTestModuleFactory() android.Module {
90	m := customTestModuleFactoryBase()
91	android.InitAndroidModule(m)
92	return m
93}
94
95type customDefaultsModule struct {
96	android.ModuleBase
97	android.DefaultsModuleBase
98}
99
100func customDefaultsModuleFactoryBase() android.DefaultsModule {
101	module := &customDefaultsModule{}
102	module.AddProperties(&customProps{})
103	return module
104}
105
106func customDefaultsModuleFactoryBasic() android.Module {
107	return customDefaultsModuleFactoryBase()
108}
109
110func customDefaultsModuleFactory() android.Module {
111	m := customDefaultsModuleFactoryBase()
112	android.InitDefaultsModule(m)
113	return m
114}
115
116type customBazelModuleAttributes struct {
117	String_prop      string
118	String_list_prop []string
119	Arch_paths       bazel.LabelListAttribute
120}
121
122type customBazelModule struct {
123	android.BazelTargetModuleBase
124	customBazelModuleAttributes
125}
126
127func customBazelModuleFactory() android.Module {
128	module := &customBazelModule{}
129	module.AddProperties(&module.customBazelModuleAttributes)
130	android.InitBazelTargetModule(module)
131	return module
132}
133
134func (m *customBazelModule) Name() string                                          { return m.BaseModuleName() }
135func (m *customBazelModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {}
136
137func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
138	if m, ok := ctx.Module().(*customModule); ok {
139		if !m.ConvertWithBp2build(ctx) {
140			return
141		}
142
143		paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths))
144
145		for arch, props := range m.GetArchProperties(ctx, &customProps{}) {
146			if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
147				paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
148			}
149		}
150
151		attrs := &customBazelModuleAttributes{
152			String_prop:      m.props.String_prop,
153			String_list_prop: m.props.String_list_prop,
154			Arch_paths:       paths,
155		}
156
157		props := bazel.BazelTargetModuleProperties{
158			Rule_class: "custom",
159		}
160
161		ctx.CreateBazelTargetModule(customBazelModuleFactory, m.Name(), props, attrs)
162	}
163}
164
165// A bp2build mutator that uses load statements and creates a 1:M mapping from
166// module to target.
167func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
168	if m, ok := ctx.Module().(*customModule); ok {
169		if !m.ConvertWithBp2build(ctx) {
170			return
171		}
172
173		baseName := m.Name()
174		attrs := &customBazelModuleAttributes{}
175
176		myLibraryProps := bazel.BazelTargetModuleProperties{
177			Rule_class:        "my_library",
178			Bzl_load_location: "//build/bazel/rules:rules.bzl",
179		}
180		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName, myLibraryProps, attrs)
181
182		protoLibraryProps := bazel.BazelTargetModuleProperties{
183			Rule_class:        "proto_library",
184			Bzl_load_location: "//build/bazel/rules:proto.bzl",
185		}
186		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_proto_library_deps", protoLibraryProps, attrs)
187
188		myProtoLibraryProps := bazel.BazelTargetModuleProperties{
189			Rule_class:        "my_proto_library",
190			Bzl_load_location: "//build/bazel/rules:proto.bzl",
191		}
192		ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
193	}
194}
195
196// Helper method for tests to easily access the targets in a dir.
197func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) BazelTargets {
198	// TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
199	buildFileToTargets, _ := GenerateBazelTargets(codegenCtx, false)
200	return buildFileToTargets[dir]
201}
202