blob: bff809bf478d3a4d1e7b66a7236049c74db95c1d [file] [log] [blame]
Jeongik Chada36d5a2021-01-20 00:43:34 +09001// Copyright (C) 2021 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 aidl
16
17import (
18 "android/soong/android"
19 "android/soong/cc"
20 "android/soong/java"
21 "android/soong/rust"
22
23 "path/filepath"
Jeongik Chada36d5a2021-01-20 00:43:34 +090024 "strings"
25
26 "github.com/google/blueprint/proptools"
27)
28
Jeongik Cha52e98022021-01-20 18:37:20 +090029func addLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
30 if lang == langJava {
31 return addJavaLibrary(mctx, i, version)
32 } else if lang == langRust {
33 return addRustLibrary(mctx, i, version)
34 }
35 return addCppLibrary(mctx, i, version, lang)
36}
37
38func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
39 cppSourceGen := i.versionedName(version) + "-" + lang + "-source"
40 cppModuleGen := i.versionedName(version) + "-" + lang
41
Jeongik Chada36d5a2021-01-20 00:43:34 +090042 srcs, aidlRoot := i.srcsForVersion(mctx, version)
43 if len(srcs) == 0 {
44 // This can happen when the version is about to be frozen; the version
45 // directory is created but API dump hasn't been copied there.
46 // Don't create a library for the yet-to-be-frozen version.
47 return ""
48 }
49
50 var overrideVndkProperties cc.VndkProperties
51
Jeongik Cha52e98022021-01-20 18:37:20 +090052 if !i.isModuleForVndk(version) {
Jeongik Chada36d5a2021-01-20 00:43:34 +090053 // We only want the VNDK to include the latest interface. For interfaces in
54 // development, they will be frozen, so we put their latest version in the
55 // VNDK. For interfaces which are already frozen, we put their latest version
56 // in the VNDK, and when that version is frozen, the version in the VNDK can
57 // be updated. Otherwise, we remove this library from the VNDK, to avoid adding
58 // multiple versions of the same library to the VNDK.
59 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
60 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
61 }
62
63 var commonProperties *CommonNativeBackendProperties
64 if lang == langCpp {
65 commonProperties = &i.properties.Backend.Cpp.CommonNativeBackendProperties
66 } else if lang == langNdk || lang == langNdkPlatform {
67 commonProperties = &i.properties.Backend.Ndk.CommonNativeBackendProperties
68 }
69
70 genLog := proptools.Bool(commonProperties.Gen_log)
71 genTrace := proptools.Bool(i.properties.Gen_trace)
72
73 mctx.CreateModule(aidlGenFactory, &nameProperties{
74 Name: proptools.StringPtr(cppSourceGen),
75 }, &aidlGenProperties{
Jeongik Chaa01447d2021-03-17 17:43:12 +090076 Srcs: srcs,
77 AidlRoot: aidlRoot,
Jooyung Han60699b52021-05-26 22:20:42 +090078 IsToT: version == i.nextVersion(),
79 ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
Jeongik Chaa01447d2021-03-17 17:43:12 +090080 Stability: i.properties.Stability,
81 Lang: lang,
82 BaseName: i.ModuleBase.Name(),
83 GenLog: genLog,
84 Version: i.versionForAidlGenRule(version),
85 GenTrace: genTrace,
86 Unstable: i.properties.Unstable,
87 Visibility: srcsVisibility(mctx, lang),
88 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +090089 })
Jeongik Chada36d5a2021-01-20 00:43:34 +090090
Jeongik Cha52e98022021-01-20 18:37:20 +090091 importExportDependencies := []string{}
Jeongik Chada36d5a2021-01-20 00:43:34 +090092 var sharedLibDependency []string
93 var headerLibs []string
94 var sdkVersion *string
95 var minSdkVersion *string
96 var stl *string
97 var cpp_std *string
98 var hostSupported *bool
99 var addCflags []string
100
101 if lang == langCpp {
102 importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
103 if genTrace {
104 sharedLibDependency = append(sharedLibDependency, "libcutils")
105 }
106 hostSupported = i.properties.Host_supported
107 minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
108 } else if lang == langNdk {
109 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
110 if genTrace {
111 sharedLibDependency = append(sharedLibDependency, "libandroid")
112 }
113 sdkVersion = proptools.StringPtr("current")
114 stl = proptools.StringPtr("c++_shared")
115 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
116 } else if lang == langNdkPlatform {
117 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
118 if genTrace {
119 headerLibs = append(headerLibs, "libandroid_aidltrace")
120 sharedLibDependency = append(sharedLibDependency, "libcutils")
121 }
122 hostSupported = i.properties.Host_supported
123 addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
124 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
125 } else {
126 panic("Unrecognized language: " + lang)
127 }
128
129 vendorAvailable := i.properties.Vendor_available
Justin Yun08cb78a2021-01-25 17:24:24 +0900130 odmAvailable := i.properties.Odm_available
Jeongik Chada36d5a2021-01-20 00:43:34 +0900131 productAvailable := i.properties.Product_available
132 if lang == langCpp {
133 // Vendor and product modules cannot use the libbinder (cpp) backend of AIDL in a
134 // way that is stable. So, in order to prevent accidental usage of these library by
135 // vendor and product forcibly disabling this version of the library.
136 //
137 // It may be the case in the future that we will want to enable this (if some generic
138 // helper should be used by both libbinder vendor things using /dev/vndbinder as well
139 // as those things using /dev/binder + libbinder_ndk to talk to stable interfaces).
140 if "vintf" == proptools.String(i.properties.Stability) {
141 overrideVndkProperties.Vndk.Private = proptools.BoolPtr(true)
142 }
143 // As libbinder is not available for the product processes, we must not create
144 // product variant for the aidl_interface
145 productAvailable = nil
146 }
147
148 if lang == langNdk {
149 // TODO(b/121157555): when the NDK variant is its own variant, these wouldn't interact,
150 // but we can't create a vendor or product version of an NDK variant
151 //
152 // nil (unspecified) is used instead of false so that this can't conflict with
153 // 'vendor: true', for instance.
154 vendorAvailable = nil
Justin Yun08cb78a2021-01-25 17:24:24 +0900155 odmAvailable = nil
Jeongik Chada36d5a2021-01-20 00:43:34 +0900156 productAvailable = nil
157 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
158 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
159 }
160
Jeongik Cha52e98022021-01-20 18:37:20 +0900161 mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
162 Name: proptools.StringPtr(cppModuleGen + "-generator"),
163 }, &aidlImplementationGeneratorProperties{
164 Lang: lang,
165 AidlInterfaceName: i.ModuleBase.Name(),
166 Version: version,
167 ModuleProperties: []interface{}{
168 &ccProperties{
169 Name: proptools.StringPtr(cppModuleGen),
170 Vendor_available: vendorAvailable,
Justin Yun08cb78a2021-01-25 17:24:24 +0900171 Odm_available: odmAvailable,
Jeongik Cha52e98022021-01-20 18:37:20 +0900172 Product_available: productAvailable,
173 Host_supported: hostSupported,
174 Defaults: []string{"aidl-cpp-module-defaults"},
175 Double_loadable: i.properties.Double_loadable,
176 Generated_sources: []string{cppSourceGen},
177 Generated_headers: []string{cppSourceGen},
178 Export_generated_headers: []string{cppSourceGen},
179 Shared_libs: append(importExportDependencies, sharedLibDependency...),
180 Header_libs: headerLibs,
181 Export_shared_lib_headers: importExportDependencies,
182 Sdk_version: sdkVersion,
183 Stl: stl,
184 Cpp_std: cpp_std,
185 Cflags: append(addCflags, "-Wextra", "-Wall", "-Werror", "-Wextra-semi"),
186 Apex_available: commonProperties.Apex_available,
187 Min_sdk_version: minSdkVersion,
188 UseApexNameMacro: true,
189 Target: ccTargetProperties{
190 // Currently necessary for host builds
191 // TODO(b/31559095): bionic on host should define this
192 // TODO(b/146436251): default isn't applied because the module is created
193 // in PreArchMutators, when import behavior becomes explicit, the logic can
194 // be moved back to LoadHook
195 Host: hostProperties{Cflags: []string{
196 "-D__INTRODUCED_IN(n)=",
197 "-D__assert(a,b,c)=",
198 // We want all the APIs to be available on the host.
199 "-D__ANDROID_API__=10000"}},
200 Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
201 Tidy: proptools.BoolPtr(true),
202 // Do the tidy check only for the generated headers
203 Tidy_flags: []string{"--header-filter=" + android.PathForOutput(mctx).String() + ".*"},
204 Tidy_checks_as_errors: []string{"*"},
205 }, &i.properties.VndkProperties,
206 &commonProperties.VndkProperties,
207 &overrideVndkProperties,
208 },
209 })
Jeongik Chada36d5a2021-01-20 00:43:34 +0900210
211 return cppModuleGen
212}
213
Jeongik Cha52e98022021-01-20 18:37:20 +0900214func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
215 javaSourceGen := i.versionedName(version) + "-java-source"
216 javaModuleGen := i.versionedName(version) + "-java"
Jeongik Chada36d5a2021-01-20 00:43:34 +0900217 srcs, aidlRoot := i.srcsForVersion(mctx, version)
218 if len(srcs) == 0 {
219 // This can happen when the version is about to be frozen; the version
220 // directory is created but API dump hasn't been copied there.
221 // Don't create a library for the yet-to-be-frozen version.
222 return ""
223 }
224
225 sdkVersion := i.properties.Backend.Java.Sdk_version
226 if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
227 // platform apis requires no default
228 sdkVersion = proptools.StringPtr("system_current")
229 }
230
231 mctx.CreateModule(aidlGenFactory, &nameProperties{
232 Name: proptools.StringPtr(javaSourceGen),
233 }, &aidlGenProperties{
Jeongik Chaa01447d2021-03-17 17:43:12 +0900234 Srcs: srcs,
235 AidlRoot: aidlRoot,
Jooyung Han60699b52021-05-26 22:20:42 +0900236 IsToT: version == i.nextVersion(),
237 ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
Jeongik Chaa01447d2021-03-17 17:43:12 +0900238 Stability: i.properties.Stability,
239 Lang: langJava,
240 BaseName: i.ModuleBase.Name(),
241 Version: i.versionForAidlGenRule(version),
242 GenTrace: proptools.Bool(i.properties.Gen_trace),
243 Unstable: i.properties.Unstable,
244 Visibility: srcsVisibility(mctx, langJava),
245 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900246 })
247
Jeongik Cha52e98022021-01-20 18:37:20 +0900248 mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
249 Name: proptools.StringPtr(javaModuleGen + "-generator"),
250 }, &aidlImplementationGeneratorProperties{
251 Lang: langJava,
252 AidlInterfaceName: i.ModuleBase.Name(),
253 Version: version,
254 ModuleProperties: []interface{}{&javaProperties{
255 Name: proptools.StringPtr(javaModuleGen),
256 Installable: proptools.BoolPtr(true),
257 Defaults: []string{"aidl-java-module-defaults"},
258 Sdk_version: sdkVersion,
259 Platform_apis: i.properties.Backend.Java.Platform_apis,
260 Srcs: []string{":" + javaSourceGen},
261 Apex_available: i.properties.Backend.Java.Apex_available,
262 Min_sdk_version: i.properties.Backend.Java.Min_sdk_version,
263 }},
Jeongik Chada36d5a2021-01-20 00:43:34 +0900264 })
265
266 return javaModuleGen
267}
268
Jeongik Cha52e98022021-01-20 18:37:20 +0900269func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
270 rustSourceGen := i.versionedName(version) + "-rust-source"
271 rustModuleGen := i.versionedName(version) + "-rust"
Jeongik Chada36d5a2021-01-20 00:43:34 +0900272 srcs, aidlRoot := i.srcsForVersion(mctx, version)
273 if len(srcs) == 0 {
274 // This can happen when the version is about to be frozen; the version
275 // directory is created but API dump hasn't been copied there.
276 // Don't create a library for the yet-to-be-frozen version.
277 return ""
278 }
279
280 mctx.CreateModule(aidlGenFactory, &nameProperties{
281 Name: proptools.StringPtr(rustSourceGen),
282 }, &aidlGenProperties{
Jeongik Chaa01447d2021-03-17 17:43:12 +0900283 Srcs: srcs,
284 AidlRoot: aidlRoot,
Jooyung Han60699b52021-05-26 22:20:42 +0900285 ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
286 IsToT: version == i.nextVersion(),
Jeongik Chaa01447d2021-03-17 17:43:12 +0900287 Stability: i.properties.Stability,
288 Lang: langRust,
289 BaseName: i.ModuleBase.Name(),
290 Version: i.versionForAidlGenRule(version),
291 Unstable: i.properties.Unstable,
292 Visibility: srcsVisibility(mctx, langRust),
293 Flags: i.flagsForAidlGenRule(version),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900294 })
295
Jeongik Cha52e98022021-01-20 18:37:20 +0900296 versionedRustName := fixRustName(i.versionedName(version))
297 rustCrateName := fixRustName(i.ModuleBase.Name())
Jeongik Chada36d5a2021-01-20 00:43:34 +0900298
299 mctx.CreateModule(aidlRustLibraryFactory, &rustProperties{
300 Name: proptools.StringPtr(rustModuleGen),
Jeongik Cha52e98022021-01-20 18:37:20 +0900301 Crate_name: rustCrateName,
Jeongik Chada36d5a2021-01-20 00:43:34 +0900302 Stem: proptools.StringPtr("lib" + versionedRustName),
303 Defaults: []string{"aidl-rust-module-defaults"},
304 Host_supported: i.properties.Host_supported,
Jiyong Park33690252021-02-16 13:21:40 +0900305 Apex_available: i.properties.Backend.Rust.Apex_available,
Jeongik Cha52e98022021-01-20 18:37:20 +0900306 Target: rustTargetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
Jeongik Chada36d5a2021-01-20 00:43:34 +0900307 }, &rust.SourceProviderProperties{
308 Source_stem: proptools.StringPtr(versionedRustName),
309 }, &aidlRustSourceProviderProperties{
Jeongik Cha52e98022021-01-20 18:37:20 +0900310 SourceGen: rustSourceGen,
311 Imports: i.properties.Imports,
312 Version: version,
313 AidlInterfaceName: i.ModuleBase.Name(),
Jeongik Chada36d5a2021-01-20 00:43:34 +0900314 })
315
316 return rustModuleGen
317}
318
319// This function returns module name with version. Assume that there is foo of which latest version is 2
320// Version -> Module name
321// "1"->foo-V1
322// "2"->foo-V2
Jeongik Cha52e98022021-01-20 18:37:20 +0900323// "3"->foo-V3
324// And assume that there is 'bar' which is an 'unstable' interface.
325// ""->bar
Jeongik Chada36d5a2021-01-20 00:43:34 +0900326func (i *aidlInterface) versionedName(version string) string {
327 name := i.ModuleBase.Name()
328 if version == "" {
329 return name
Jeongik Chada36d5a2021-01-20 00:43:34 +0900330 }
331 return name + "-V" + version
332}
333
Jeongik Chada36d5a2021-01-20 00:43:34 +0900334func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
Jeongik Cha52e98022021-01-20 18:37:20 +0900335 if version == i.nextVersion() {
Jeongik Chada36d5a2021-01-20 00:43:34 +0900336 return i.properties.Srcs, i.properties.Local_include_dir
337 } else {
338 aidlRoot = filepath.Join(aidlApiDir, i.ModuleBase.Name(), version)
339 full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), aidlRoot, "**/*.aidl"), nil)
340 if err != nil {
341 panic(err)
342 }
343 for _, path := range full_paths {
344 // Here, we need path local to the module
345 srcs = append(srcs, strings.TrimPrefix(path, mctx.ModuleDir()+"/"))
346 }
347 return srcs, aidlRoot
348 }
349}
Jeongik Cha52e98022021-01-20 18:37:20 +0900350
351func (i *aidlInterface) versionForAidlGenRule(version string) string {
352 if !i.hasVersion() {
353 return ""
354 }
Jeongik Cha52e98022021-01-20 18:37:20 +0900355 return version
356}
357
Jooyung Han03b19c32021-02-09 10:08:19 +0900358func (i *aidlInterface) flagsForAidlGenRule(version string) (flags []string) {
359 flags = append(flags, i.properties.Flags...)
360 // For ToT, turn on "-Weverything" (enable all warnings)
361 if version == i.nextVersion() {
362 flags = append(flags, "-Weverything")
363 }
364 return
365}
366
Jeongik Cha52e98022021-01-20 18:37:20 +0900367func (i *aidlInterface) isModuleForVndk(version string) bool {
Jeongik Cha52e98022021-01-20 18:37:20 +0900368 if i.properties.Vndk_use_version != nil {
369 if !i.hasVersion() {
370 panic("does not make sense, vndk_use_version specififed")
371 }
372 // Will be exactly one of the version numbers
373 return version == *i.properties.Vndk_use_version
374 }
375
376 // For an interface with no versions, this is the ToT interface.
377 if !i.hasVersion() {
378 return version == i.nextVersion()
379 }
380
381 return version == i.latestVersion()
382}
383
384// importing aidl_interface's version | imported aidl_interface | imported aidl_interface's version
385// --------------------------------------------------------------------------------------------------
386// whatever | unstable | unstable version
387// ToT version(including unstable) | whatever | ToT version(unstable if unstable)
388// otherwise | whatever | the latest stable version
Jeongik Chaa01447d2021-03-17 17:43:12 +0900389// In the case that import specifies the version which it wants to use, use that version.
Jeongik Cha52e98022021-01-20 18:37:20 +0900390func (i *aidlInterface) getImportWithVersion(version string, anImport string, config android.Config) string {
Jeongik Chaa01447d2021-03-17 17:43:12 +0900391 if hasVersionSuffix(anImport) {
392 return anImport
393 }
Jeongik Cha52e98022021-01-20 18:37:20 +0900394 other := lookupInterface(anImport, config)
395 if proptools.Bool(other.properties.Unstable) {
396 return anImport
397 }
398 if version == i.nextVersion() || !other.hasVersion() {
399 return other.versionedName(other.nextVersion())
400 }
401 return other.versionedName(other.latestVersion())
402}
403
Jeongik Cha52e98022021-01-20 18:37:20 +0900404func aidlImplementationGeneratorFactory() android.Module {
405 g := &aidlImplementationGenerator{}
406 g.AddProperties(&g.properties)
407 android.InitAndroidModule(g)
408 return g
409}
410
411type aidlImplementationGenerator struct {
412 android.ModuleBase
413 properties aidlImplementationGeneratorProperties
414}
415
416type aidlImplementationGeneratorProperties struct {
417 Lang string
418 AidlInterfaceName string
419 Version string
420 ModuleProperties []interface{}
421}
422
423func (g *aidlImplementationGenerator) DepsMutator(ctx android.BottomUpMutatorContext) {
424}
425
426func (g *aidlImplementationGenerator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
427}
428
429func (g *aidlImplementationGenerator) GenerateImplementation(ctx android.TopDownMutatorContext) {
430 i := lookupInterface(g.properties.AidlInterfaceName, ctx.Config())
431 version := g.properties.Version
432 lang := g.properties.Lang
Jeongik Cha50a1dfc2021-05-25 23:54:20 +0900433 imports := make([]string, len(i.properties.Imports))
434 for idx, anImport := range i.properties.Imports {
435 importModule, _ := parseModuleWithVersion(anImport)
436 if lookupInterface(importModule, ctx.Config()) == nil {
437 if ctx.Config().AllowMissingDependencies() {
438 continue
439 }
440 panic(anImport + " doesn't exist, it should be checked in 'checkImports' mutator.")
Jeongik Cha52e98022021-01-20 18:37:20 +0900441 }
Jeongik Cha50a1dfc2021-05-25 23:54:20 +0900442 imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + lang
443 }
444
445 if g.properties.Lang == langJava {
Jeongik Cha52e98022021-01-20 18:37:20 +0900446 if p, ok := g.properties.ModuleProperties[0].(*javaProperties); ok {
447 p.Static_libs = imports
448 }
449 ctx.CreateModule(java.LibraryFactory, g.properties.ModuleProperties...)
450 } else {
Jeongik Cha52e98022021-01-20 18:37:20 +0900451 if p, ok := g.properties.ModuleProperties[0].(*ccProperties); ok {
452 p.Shared_libs = append(p.Shared_libs, imports...)
453 p.Export_shared_lib_headers = append(p.Export_shared_lib_headers, imports...)
454 }
455 ctx.CreateModule(cc.LibraryFactory, g.properties.ModuleProperties...)
456 }
457}