blob: a38a899c966f470253557c0e0fe6bc536717e74d [file] [log] [blame]
Steven Morelandd56e5bb2017-07-18 22:04:16 -07001// Copyright (C) 2017 The Android Open Source Project
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 hidl
16
17import (
18 "strings"
19 "sync"
20
21 "github.com/google/blueprint/proptools"
22
23 "android/soong/android"
24 "android/soong/cc"
25 "android/soong/genrule"
26 "android/soong/java"
27)
28
29var (
30 hidlInterfaceSuffix = "_interface"
31)
32
33func init() {
34 android.RegisterModuleType("hidl_interface", hidlInterfaceFactory)
35}
36
37type hidlInterfaceProperties struct {
38 // Vndk properties for interface library only.
39 cc.VndkProperties
40
41 // List of .hal files which compose this interface.
42 Srcs []string
43
44 // List of hal interface packages that this library depends on.
45 Interfaces []string
46
47 // Package root for this package, must be a prefix of name
48 Root string
49
50 // List of non-TypeDef types declared in types.hal.
51 Types []string
52
53 // Whether to generate the Java library stubs.
54 // Default: true
55 Gen_java *bool
56
57 // Whether to generate a Java library containing constants
58 // expressed by @export annotations in the hal files.
59 Gen_java_constants bool
60
61 // Don't generate "android.hidl.foo@1.0" C library. Instead
62 // only generate the genrules so that this package can be
63 // included in libhidltransport.
64 Core_interface bool
65}
66
67type hidlInterface struct {
68 android.ModuleBase
69
70 properties hidlInterfaceProperties
71}
72
73var _ genrule.SourceFileGenerator = (*hidlInterface)(nil)
74
75func processSources(mctx android.LoadHookContext, srcs []string) ([]string, []string, bool) {
76 var interfaces []string
77 var types []string // hidl-gen only supports types.hal, but don't assume that here
78
79 hasError := false
80
81 for _, v := range srcs {
82 if !strings.HasSuffix(v, ".hal") {
83 mctx.PropertyErrorf("srcs", "Source must be a .hal file: "+v)
84 hasError = true
85 continue
86 }
87
88 name := strings.TrimSuffix(v, ".hal")
89
90 if strings.HasPrefix(name, "I") {
91 baseName := strings.TrimPrefix(name, "I")
92 interfaces = append(interfaces, baseName)
93 } else {
94 types = append(types, name)
95 }
96 }
97
98 return interfaces, types, !hasError
99}
100
101func processDependencies(mctx android.LoadHookContext, interfaces []string) ([]string, []string, bool) {
102 var dependencies []string
103 var javaDependencies []string
104
105 hasError := false
106
107 for _, v := range interfaces {
108 name, err := parseFqName(v)
109 if err != nil {
110 mctx.PropertyErrorf("interfaces", err.Error())
111 hasError = true
112 continue
113 }
114 dependencies = append(dependencies, name.string())
115 javaDependencies = append(javaDependencies, name.javaName())
116 }
117
118 return dependencies, javaDependencies, !hasError
119}
120
121func getRootList(mctx android.LoadHookContext, interfaces []string) ([]string, bool) {
122 var roots []string
123 hasError := false
124
125 for _, i := range interfaces {
126 interfaceObject := lookupInterface(i)
127 if interfaceObject == nil {
128 mctx.PropertyErrorf("interfaces", "Cannot find interface "+i)
129 hasError = true
130 continue
131 }
132 root := interfaceObject.properties.Root
133 rootObject := lookupPackageRoot(root)
134 if rootObject == nil {
135 mctx.PropertyErrorf("interfaces", "Cannot find package root for "+i+" which is '"+root+"'")
136 hasError = true
137 continue
138 }
139
140 roots = append(roots, root+":"+rootObject.properties.Path)
141 }
142
143 return android.FirstUniqueStrings(roots), !hasError
144}
145
146func removeCoreDependencies(mctx android.LoadHookContext, dependencies []string) ([]string, bool) {
147 var ret []string
148 hasError := false
149
150 for _, i := range dependencies {
151 interfaceObject := lookupInterface(i)
152 if interfaceObject == nil {
153 mctx.PropertyErrorf("interfaces", "Cannot find interface "+i)
154 hasError = true
155 continue
156 }
157
158 if !interfaceObject.properties.Core_interface {
159 ret = append(ret, i)
160 }
161 }
162
163 return ret, !hasError
164}
165
166func hidlGenCommand(lang string, roots []string, name *fqName) *string {
167 cmd := "$(location hidl-gen) -o $(genDir)"
168 cmd += " -L" + lang
169 cmd += " " + strings.Join(wrap("-r", roots, ""), " ")
170 cmd += " " + name.string()
171 return &cmd
172}
173
174func hidlInterfaceMutator(mctx android.LoadHookContext, i *hidlInterface) {
175 name, err := parseFqName(i.ModuleBase.Name())
176 if err != nil {
177 mctx.PropertyErrorf("name", err.Error())
178 }
179
180 if !name.inPackage(i.properties.Root) {
181 mctx.PropertyErrorf("root", "Root, "+i.properties.Root+", for "+name.string()+" must be a prefix.")
182 }
183
184 interfaces, types, _ := processSources(mctx, i.properties.Srcs)
185
186 if len(interfaces) == 0 && len(types) == 0 {
187 mctx.PropertyErrorf("srcs", "No sources provided.")
188 }
189
190 dependencies, javaDependencies, _ := processDependencies(mctx, i.properties.Interfaces)
Steven Moreland12ff1262017-11-13 13:35:37 -0800191 roots, _ := getRootList(mctx, append(dependencies, name.string()))
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700192 cppDependencies, _ := removeCoreDependencies(mctx, dependencies)
193
194 if mctx.Failed() {
195 return
196 }
197
198 shouldGenerateLibrary := !i.properties.Core_interface
199 // explicitly true if not specified to give early warning to devs
200 shouldGenerateJava := i.properties.Gen_java == nil || *i.properties.Gen_java
201 shouldGenerateJavaConstants := i.properties.Gen_java_constants
202
203 var libraryIfExists []string
204 if shouldGenerateLibrary {
205 libraryIfExists = []string{name.string()}
206 }
207
208 // TODO(b/69002743): remove filegroups
209 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.FileGroupFactory), &fileGroupProperties{
210 Name: proptools.StringPtr(name.fileGroupName()),
211 Srcs: i.properties.Srcs,
212 })
213
214 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
215 Name: proptools.StringPtr(name.sourcesName()),
216 Tools: []string{"hidl-gen"},
217 Cmd: hidlGenCommand("c++-sources", roots, name),
218 Srcs: i.properties.Srcs,
219 Out: concat(wrap(name.dir(), interfaces, "All.cpp"),
220 wrap(name.dir(), types, ".cpp")),
221 })
222 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
223 Name: proptools.StringPtr(name.headersName()),
224 Tools: []string{"hidl-gen"},
225 Cmd: hidlGenCommand("c++-headers", roots, name),
226 Srcs: i.properties.Srcs,
227 Out: concat(wrap(name.dir()+"I", interfaces, ".h"),
228 wrap(name.dir()+"Bs", interfaces, ".h"),
229 wrap(name.dir()+"BnHw", interfaces, ".h"),
230 wrap(name.dir()+"BpHw", interfaces, ".h"),
231 wrap(name.dir()+"IHw", interfaces, ".h"),
232 wrap(name.dir(), types, ".h"),
233 wrap(name.dir()+"hw", types, ".h")),
234 })
235
236 if shouldGenerateLibrary {
237 mctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProperties{
238 Name: proptools.StringPtr(name.string()),
239 Vendor_available: proptools.BoolPtr(true),
240 Defaults: []string{"hidl-module-defaults"},
241 Generated_sources: []string{name.sourcesName()},
242 Generated_headers: []string{name.headersName()},
243 Shared_libs: concat(cppDependencies, []string{
244 "libhidlbase",
245 "libhidltransport",
246 "libhwbinder",
247 "liblog",
248 "libutils",
249 "libcutils",
250 }),
251 Export_shared_lib_headers: concat(cppDependencies, []string{
252 "libhidlbase",
253 "libhidltransport",
254 "libhwbinder",
255 "libutils",
256 }),
257 Export_generated_headers: []string{name.headersName()},
258 }, &i.properties.VndkProperties)
259 }
260
261 if shouldGenerateJava {
262 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
263 Name: proptools.StringPtr(name.javaSourcesName()),
264 Tools: []string{"hidl-gen"},
265 Cmd: hidlGenCommand("java", roots, name),
266 Srcs: i.properties.Srcs,
267 Out: concat(wrap(name.sanitizedDir()+"I", interfaces, ".java"),
268 wrap(name.sanitizedDir(), i.properties.Types, ".java")),
269 })
270 mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory(true)), &javaProperties{
271 Name: proptools.StringPtr(name.javaName()),
272 Defaults: []string{"hidl-java-module-defaults"},
273 No_framework_libs: proptools.BoolPtr(true),
274 Srcs: []string{":" + name.javaSourcesName()},
275 Libs: append(javaDependencies, "hwbinder"),
276 })
277 }
278
279 if shouldGenerateJavaConstants {
280 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
281 Name: proptools.StringPtr(name.javaConstantsSourcesName()),
282 Tools: []string{"hidl-gen"},
283 Cmd: hidlGenCommand("java-constants", roots, name),
284 Srcs: i.properties.Srcs,
285 Out: []string{name.sanitizedDir() + "Constants.java"},
286 })
287 mctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory(true)), &javaProperties{
288 Name: proptools.StringPtr(name.javaConstantsName()),
289 Defaults: []string{"hidl-java-module-defaults"},
290 No_framework_libs: proptools.BoolPtr(true),
291 Srcs: []string{":" + name.javaConstantsSourcesName()},
292 })
293 }
294
295 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
296 Name: proptools.StringPtr(name.adapterHelperSourcesName()),
297 Tools: []string{"hidl-gen"},
298 Cmd: hidlGenCommand("c++-adapter-sources", roots, name),
299 Srcs: i.properties.Srcs,
300 Out: wrap(name.dir()+"A", concat(interfaces, types), ".cpp"),
301 })
302 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
303 Name: proptools.StringPtr(name.adapterHelperHeadersName()),
304 Tools: []string{"hidl-gen"},
305 Cmd: hidlGenCommand("c++-adapter-headers", roots, name),
306 Srcs: i.properties.Srcs,
307 Out: wrap(name.dir()+"A", concat(interfaces, types), ".h"),
308 })
309
310 mctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProperties{
311 Name: proptools.StringPtr(name.adapterHelperName()),
312 Vendor_available: proptools.BoolPtr(true),
313 Defaults: []string{"hidl-module-defaults"},
314 Generated_sources: []string{name.adapterHelperSourcesName()},
315 Generated_headers: []string{name.adapterHelperHeadersName()},
Steven Moreland10d1ec42017-11-29 13:56:28 -0800316 Shared_libs: []string{
Steven Morelandffa25282017-11-13 14:23:25 -0800317 "libcutils",
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700318 "libhidlbase",
319 "libhidltransport",
Steven Morelandffa25282017-11-13 14:23:25 -0800320 "libhwbinder",
321 "liblog",
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700322 "libutils",
Steven Morelandffa25282017-11-13 14:23:25 -0800323 },
324 Static_libs: concat([]string{
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700325 "libhidladapter",
326 }, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
Steven Morelandffa25282017-11-13 14:23:25 -0800327 Export_shared_lib_headers: []string{
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700328 "libhidlbase",
329 "libhidltransport",
Steven Morelandffa25282017-11-13 14:23:25 -0800330 },
331 Export_static_lib_headers: concat([]string{
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700332 "libhidladapter",
333 }, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
334 Export_generated_headers: []string{name.adapterHelperHeadersName()},
Steven Moreland10d1ec42017-11-29 13:56:28 -0800335 Group_static_libs: proptools.BoolPtr(true),
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700336 })
337 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProperties{
338 Name: proptools.StringPtr(name.adapterSourcesName()),
339 Tools: []string{"hidl-gen"},
340 Cmd: hidlGenCommand("c++-adapter-main", roots, name),
341 Srcs: i.properties.Srcs,
342 Out: []string{"main.cpp"},
343 })
344 mctx.CreateModule(android.ModuleFactoryAdaptor(cc.TestFactory), &ccProperties{
345 Name: proptools.StringPtr(name.adapterName()),
346 Generated_sources: []string{name.adapterSourcesName()},
Steven Moreland10d1ec42017-11-29 13:56:28 -0800347 Shared_libs: []string{
Steven Morelandffa25282017-11-13 14:23:25 -0800348 "libcutils",
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700349 "libhidlbase",
350 "libhidltransport",
Steven Morelandffa25282017-11-13 14:23:25 -0800351 "libhwbinder",
352 "liblog",
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700353 "libutils",
Steven Morelandffa25282017-11-13 14:23:25 -0800354 },
355 Static_libs: concat([]string{
356 "libhidladapter",
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700357 name.adapterHelperName(),
Steven Morelandffa25282017-11-13 14:23:25 -0800358 }, wrap("", dependencies, "-adapter-helper"), cppDependencies, libraryIfExists),
359 Group_static_libs: proptools.BoolPtr(true),
Steven Morelandd56e5bb2017-07-18 22:04:16 -0700360 })
361}
362
363func (h *hidlInterface) Name() string {
364 return h.ModuleBase.Name() + hidlInterfaceSuffix
365}
366func (h *hidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
367}
368func (h *hidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
369}
370func (h *hidlInterface) GeneratedHeaderDirs() android.Paths {
371 return []android.Path{}
372}
373func (h *hidlInterface) GeneratedSourceFiles() android.Paths {
374 return []android.Path{}
375}
376
377var hidlInterfaceMutex sync.Mutex
378var hidlInterfaces []*hidlInterface
379
380func hidlInterfaceFactory() android.Module {
381 i := &hidlInterface{}
382 i.AddProperties(&i.properties)
383 android.InitAndroidModule(i)
384 android.AddLoadHook(i, func(ctx android.LoadHookContext) { hidlInterfaceMutator(ctx, i) })
385
386 hidlInterfaceMutex.Lock()
387 hidlInterfaces = append(hidlInterfaces, i)
388 hidlInterfaceMutex.Unlock()
389
390 return i
391}
392
393func lookupInterface(name string) *hidlInterface {
394 for _, i := range hidlInterfaces {
395 if i.ModuleBase.Name() == name {
396 return i
397 }
398 }
399 return nil
400}