blob: 53b4b73efa95909e22b5d158c6cd15aa237e5563 [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"
24 "strconv"
25 "strings"
26
27 "github.com/google/blueprint/proptools"
28)
29
30func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, versionForModuleName string, lang string) string {
31 cppSourceGen := i.versionedName(versionForModuleName) + "-" + lang + "-source"
32 cppModuleGen := i.versionedName(versionForModuleName) + "-" + lang
33 cppOutputGen := i.cppOutputName(versionForModuleName) + "-" + lang
34 version := i.normalizeVersion(versionForModuleName)
35 srcs, aidlRoot := i.srcsForVersion(mctx, version)
36 if len(srcs) == 0 {
37 // This can happen when the version is about to be frozen; the version
38 // directory is created but API dump hasn't been copied there.
39 // Don't create a library for the yet-to-be-frozen version.
40 return ""
41 }
42
43 var overrideVndkProperties cc.VndkProperties
44
45 if i.moduleVersionForVndk() != versionForModuleName {
46 // We only want the VNDK to include the latest interface. For interfaces in
47 // development, they will be frozen, so we put their latest version in the
48 // VNDK. For interfaces which are already frozen, we put their latest version
49 // in the VNDK, and when that version is frozen, the version in the VNDK can
50 // be updated. Otherwise, we remove this library from the VNDK, to avoid adding
51 // multiple versions of the same library to the VNDK.
52 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
53 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
54 }
55
56 var commonProperties *CommonNativeBackendProperties
57 if lang == langCpp {
58 commonProperties = &i.properties.Backend.Cpp.CommonNativeBackendProperties
59 } else if lang == langNdk || lang == langNdkPlatform {
60 commonProperties = &i.properties.Backend.Ndk.CommonNativeBackendProperties
61 }
62
63 genLog := proptools.Bool(commonProperties.Gen_log)
64 genTrace := proptools.Bool(i.properties.Gen_trace)
65
66 mctx.CreateModule(aidlGenFactory, &nameProperties{
67 Name: proptools.StringPtr(cppSourceGen),
68 }, &aidlGenProperties{
69 Srcs: srcs,
70 AidlRoot: aidlRoot,
71 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
72 Stability: i.properties.Stability,
73 Lang: lang,
74 BaseName: i.ModuleBase.Name(),
75 GenLog: genLog,
76 Version: version,
77 GenTrace: genTrace,
78 Unstable: i.properties.Unstable,
79 Visibility: srcsVisibility(mctx, lang),
80 Flags: i.properties.Flags,
81 })
82 importPostfix := i.getImportPostfix(mctx, version, lang)
83
84 importExportDependencies := wrap("", i.properties.Imports, importPostfix)
85 var sharedLibDependency []string
86 var headerLibs []string
87 var sdkVersion *string
88 var minSdkVersion *string
89 var stl *string
90 var cpp_std *string
91 var hostSupported *bool
92 var addCflags []string
93
94 if lang == langCpp {
95 importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
96 if genTrace {
97 sharedLibDependency = append(sharedLibDependency, "libcutils")
98 }
99 hostSupported = i.properties.Host_supported
100 minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
101 } else if lang == langNdk {
102 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
103 if genTrace {
104 sharedLibDependency = append(sharedLibDependency, "libandroid")
105 }
106 sdkVersion = proptools.StringPtr("current")
107 stl = proptools.StringPtr("c++_shared")
108 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
109 } else if lang == langNdkPlatform {
110 importExportDependencies = append(importExportDependencies, "libbinder_ndk")
111 if genTrace {
112 headerLibs = append(headerLibs, "libandroid_aidltrace")
113 sharedLibDependency = append(sharedLibDependency, "libcutils")
114 }
115 hostSupported = i.properties.Host_supported
116 addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
117 minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
118 } else {
119 panic("Unrecognized language: " + lang)
120 }
121
122 vendorAvailable := i.properties.Vendor_available
123 productAvailable := i.properties.Product_available
124 if lang == langCpp {
125 // Vendor and product modules cannot use the libbinder (cpp) backend of AIDL in a
126 // way that is stable. So, in order to prevent accidental usage of these library by
127 // vendor and product forcibly disabling this version of the library.
128 //
129 // It may be the case in the future that we will want to enable this (if some generic
130 // helper should be used by both libbinder vendor things using /dev/vndbinder as well
131 // as those things using /dev/binder + libbinder_ndk to talk to stable interfaces).
132 if "vintf" == proptools.String(i.properties.Stability) {
133 overrideVndkProperties.Vndk.Private = proptools.BoolPtr(true)
134 }
135 // As libbinder is not available for the product processes, we must not create
136 // product variant for the aidl_interface
137 productAvailable = nil
138 }
139
140 if lang == langNdk {
141 // TODO(b/121157555): when the NDK variant is its own variant, these wouldn't interact,
142 // but we can't create a vendor or product version of an NDK variant
143 //
144 // nil (unspecified) is used instead of false so that this can't conflict with
145 // 'vendor: true', for instance.
146 vendorAvailable = nil
147 productAvailable = nil
148 overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
149 overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
150 }
151
152 mctx.CreateModule(cc.LibraryFactory, &ccProperties{
153 Name: proptools.StringPtr(cppModuleGen),
154 Vendor_available: vendorAvailable,
155 Product_available: productAvailable,
156 Host_supported: hostSupported,
157 Defaults: []string{"aidl-cpp-module-defaults"},
158 Double_loadable: i.properties.Double_loadable,
159 Generated_sources: []string{cppSourceGen},
160 Generated_headers: []string{cppSourceGen},
161 Export_generated_headers: []string{cppSourceGen},
162 Shared_libs: append(importExportDependencies, sharedLibDependency...),
163 Header_libs: headerLibs,
164 Export_shared_lib_headers: importExportDependencies,
165 Sdk_version: sdkVersion,
166 Stl: stl,
167 Cpp_std: cpp_std,
168 Cflags: append(addCflags, "-Wextra", "-Wall", "-Werror"),
169 Stem: proptools.StringPtr(cppOutputGen),
170 Apex_available: commonProperties.Apex_available,
171 Min_sdk_version: minSdkVersion,
172 UseApexNameMacro: true,
173 Target: targetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
174 Tidy: proptools.BoolPtr(true),
175 // Do the tidy check only for the generated headers
176 Tidy_flags: []string{"--header-filter=" + android.PathForOutput(mctx).String() + ".*"},
177 Tidy_checks_as_errors: []string{"*"},
178 }, &i.properties.VndkProperties, &commonProperties.VndkProperties, &overrideVndkProperties)
179
180 return cppModuleGen
181}
182
183func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, versionForModuleName string) string {
184 javaSourceGen := i.versionedName(versionForModuleName) + "-java-source"
185 javaModuleGen := i.versionedName(versionForModuleName) + "-java"
186 version := i.normalizeVersion(versionForModuleName)
187 srcs, aidlRoot := i.srcsForVersion(mctx, version)
188 if len(srcs) == 0 {
189 // This can happen when the version is about to be frozen; the version
190 // directory is created but API dump hasn't been copied there.
191 // Don't create a library for the yet-to-be-frozen version.
192 return ""
193 }
194
195 sdkVersion := i.properties.Backend.Java.Sdk_version
196 if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
197 // platform apis requires no default
198 sdkVersion = proptools.StringPtr("system_current")
199 }
200
201 mctx.CreateModule(aidlGenFactory, &nameProperties{
202 Name: proptools.StringPtr(javaSourceGen),
203 }, &aidlGenProperties{
204 Srcs: srcs,
205 AidlRoot: aidlRoot,
206 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
207 Stability: i.properties.Stability,
208 Lang: langJava,
209 BaseName: i.ModuleBase.Name(),
210 Version: version,
211 GenTrace: proptools.Bool(i.properties.Gen_trace),
212 Unstable: i.properties.Unstable,
213 Visibility: srcsVisibility(mctx, langJava),
214 Flags: i.properties.Flags,
215 })
216
217 importPostfix := i.getImportPostfix(mctx, version, langJava)
218 mctx.CreateModule(java.LibraryFactory, &javaProperties{
219 Name: proptools.StringPtr(javaModuleGen),
220 Installable: proptools.BoolPtr(true),
221 Defaults: []string{"aidl-java-module-defaults"},
222 Sdk_version: sdkVersion,
223 Platform_apis: i.properties.Backend.Java.Platform_apis,
224 Static_libs: wrap("", i.properties.Imports, importPostfix),
225 Srcs: []string{":" + javaSourceGen},
226 Apex_available: i.properties.Backend.Java.Apex_available,
227 Min_sdk_version: i.properties.Backend.Java.Min_sdk_version,
228 })
229
230 return javaModuleGen
231}
232
233func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, versionForModuleName string) string {
234 rustSourceGen := i.versionedName(versionForModuleName) + "-rust-source"
235 rustModuleGen := i.versionedName(versionForModuleName) + "-rust"
236 version := i.normalizeVersion(versionForModuleName)
237 srcs, aidlRoot := i.srcsForVersion(mctx, version)
238 if len(srcs) == 0 {
239 // This can happen when the version is about to be frozen; the version
240 // directory is created but API dump hasn't been copied there.
241 // Don't create a library for the yet-to-be-frozen version.
242 return ""
243 }
244
245 mctx.CreateModule(aidlGenFactory, &nameProperties{
246 Name: proptools.StringPtr(rustSourceGen),
247 }, &aidlGenProperties{
248 Srcs: srcs,
249 AidlRoot: aidlRoot,
250 Imports: concat(i.properties.Imports, []string{i.ModuleBase.Name()}),
251 Stability: i.properties.Stability,
252 Lang: langRust,
253 BaseName: i.ModuleBase.Name(),
254 Version: version,
255 Unstable: i.properties.Unstable,
256 Visibility: srcsVisibility(mctx, langRust),
257 Flags: i.properties.Flags,
258 })
259
260 versionedRustName := fixRustName(i.versionedName(versionForModuleName))
261
262 mctx.CreateModule(aidlRustLibraryFactory, &rustProperties{
263 Name: proptools.StringPtr(rustModuleGen),
264 Crate_name: versionedRustName,
265 Stem: proptools.StringPtr("lib" + versionedRustName),
266 Defaults: []string{"aidl-rust-module-defaults"},
267 Host_supported: i.properties.Host_supported,
268 Target: targetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
269 }, &rust.SourceProviderProperties{
270 Source_stem: proptools.StringPtr(versionedRustName),
271 }, &aidlRustSourceProviderProperties{
272 SourceGen: rustSourceGen,
273 Imports: i.properties.Imports,
274 })
275
276 return rustModuleGen
277}
278
279// This function returns module name with version. Assume that there is foo of which latest version is 2
280// Version -> Module name
281// "1"->foo-V1
282// "2"->foo-V2
283// "3"(unfrozen)->foo-unstable
284// ""-> foo
285// "unstable" -> foo-unstable
286func (i *aidlInterface) versionedName(version string) string {
287 name := i.ModuleBase.Name()
288 if version == "" {
289 return name
290 }
291 if version == i.currentVersion() || version == unstableVersion {
292 return name + "-" + unstableVersion
293 }
294 return name + "-V" + version
295}
296
297// This function returns C++ artifact's name. Mostly, it returns same as versionedName(),
298// But, it returns different value only if it is the case below.
299// Assume that there is foo of which latest version is 2
300// foo-unstable -> foo-V3
301// foo -> foo-V2 (latest frozen version)
302// Assume that there is bar of which version hasn't been defined yet.
303// bar -> bar
304// bar-unstable -> bar-V1
305func (i *aidlInterface) cppOutputName(version string) string {
306 name := i.ModuleBase.Name()
307 if i.hasVersion() && version == unstableVersion {
308 panic("A versioned module's output name in C++ must not contain 'unstable'")
309 }
310 // If the module doesn't have version, it returns with version(-V1) only if 'version' is unstable,
311 // otherwise, it returns the name without version.
312 if !i.hasVersion() {
313 // TODO(b/150578172): Use "-V1" as 'unstable' when the build system supports it, or remove it altogether later.
314 if version == "" {
315 return name
316 }
317 // latestVersion() always returns "0"
318 i, err := strconv.Atoi(i.latestVersion())
319 if err != nil {
320 panic(err)
321 }
322 return name + "-V" + strconv.Itoa(i+1)
323 }
324 if version == "" {
325 version = i.latestVersion()
326 }
327 return name + "-V" + version
328}
329
330func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
331 if version == i.currentVersion() {
332 return i.properties.Srcs, i.properties.Local_include_dir
333 } else {
334 aidlRoot = filepath.Join(aidlApiDir, i.ModuleBase.Name(), version)
335 full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), aidlRoot, "**/*.aidl"), nil)
336 if err != nil {
337 panic(err)
338 }
339 for _, path := range full_paths {
340 // Here, we need path local to the module
341 srcs = append(srcs, strings.TrimPrefix(path, mctx.ModuleDir()+"/"))
342 }
343 return srcs, aidlRoot
344 }
345}