blob: 730be14b0ca16310757e9f598005f72a8dcef2ae [file] [log] [blame]
Colin Cross2207f872021-03-24 12:39:08 -07001// 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 java
16
17import (
18 "fmt"
Anton Hansson86758ac2021-11-03 14:44:12 +000019 "path/filepath"
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +020020 "regexp"
Colin Cross2207f872021-03-24 12:39:08 -070021 "strings"
22
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/java/config"
27 "android/soong/remoteexec"
28)
29
Pedro Loureirocc203502021-10-04 17:24:00 +000030// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070031var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000032
Jihoon Kang6592e872023-12-19 01:13:16 +000033type StubsType int
34
35const (
36 Everything StubsType = iota
37 Runtime
38 Exportable
Jihoon Kang78f89142023-12-27 01:40:29 +000039 Unavailable
Jihoon Kang6592e872023-12-19 01:13:16 +000040)
41
42func (s StubsType) String() string {
43 switch s {
44 case Everything:
45 return "everything"
46 case Runtime:
47 return "runtime"
48 case Exportable:
49 return "exportable"
50 default:
51 return ""
52 }
53}
54
Jihoon Kang5d701272024-02-15 21:53:49 +000055func StringToStubsType(s string) StubsType {
56 switch strings.ToLower(s) {
57 case Everything.String():
58 return Everything
59 case Runtime.String():
60 return Runtime
61 case Exportable.String():
62 return Exportable
63 default:
64 return Unavailable
65 }
66}
67
Colin Cross2207f872021-03-24 12:39:08 -070068func init() {
69 RegisterStubsBuildComponents(android.InitRegistrationContext)
70}
71
72func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
73 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
74
75 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
76 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
77
78 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
79}
80
Jihoon Kangee113282024-01-23 00:16:41 +000081type stubsArtifacts struct {
82 nullabilityWarningsFile android.WritablePath
83 annotationsZip android.WritablePath
84 apiVersionsXml android.WritablePath
85 metadataZip android.WritablePath
86 metadataDir android.WritablePath
87}
88
Colin Cross2207f872021-03-24 12:39:08 -070089// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070090type Droidstubs struct {
91 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000092 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070093
Jihoon Kangee113282024-01-23 00:16:41 +000094 properties DroidstubsProperties
95 apiFile android.Path
96 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070097
98 checkCurrentApiTimestamp android.WritablePath
99 updateCurrentApiTimestamp android.WritablePath
100 checkLastReleasedApiTimestamp android.WritablePath
101 apiLintTimestamp android.WritablePath
102 apiLintReport android.WritablePath
103
104 checkNullabilityWarningsTimestamp android.WritablePath
105
Jihoon Kangee113282024-01-23 00:16:41 +0000106 everythingArtifacts stubsArtifacts
107 exportableArtifacts stubsArtifacts
Jihoon Kang3c89f042023-12-19 02:40:22 +0000108
LaMont Jonesafe7baf2024-01-09 22:47:39 +0000109 // Single aconfig "cache file" merged from this module and all dependencies.
110 mergedAconfigFiles map[string]android.Paths
111
Jihoon Kangee113282024-01-23 00:16:41 +0000112 exportableApiFile android.WritablePath
113 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700114}
115
116type DroidstubsProperties struct {
117 // The generated public API filename by Metalava, defaults to <module>_api.txt
118 Api_filename *string
119
120 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
121 Removed_api_filename *string
122
Colin Cross2207f872021-03-24 12:39:08 -0700123 Check_api struct {
124 Last_released ApiToCheck
125
126 Current ApiToCheck
127
128 Api_lint struct {
129 Enabled *bool
130
131 // If set, performs api_lint on any new APIs not found in the given signature file
132 New_since *string `android:"path"`
133
134 // If not blank, path to the baseline txt file for approved API lint violations.
135 Baseline_file *string `android:"path"`
136 }
137 }
138
139 // user can specify the version of previous released API file in order to do compatibility check.
140 Previous_api *string `android:"path"`
141
142 // is set to true, Metalava will allow framework SDK to contain annotations.
143 Annotations_enabled *bool
144
145 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
146 Merge_annotations_dirs []string
147
148 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
149 Merge_inclusion_annotations_dirs []string
150
151 // a file containing a list of classes to do nullability validation for.
152 Validate_nullability_from_list *string
153
154 // a file containing expected warnings produced by validation of nullability annotations.
155 Check_nullability_warnings *string
156
157 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
158 Create_doc_stubs *bool
159
160 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
161 // Has no effect if create_doc_stubs: true.
162 Output_javadoc_comments *bool
163
164 // if set to false then do not write out stubs. Defaults to true.
165 //
166 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
167 Generate_stubs *bool
168
169 // if set to true, provides a hint to the build system that this rule uses a lot of memory,
Liz Kammer170dd722023-10-16 15:08:39 -0400170 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700171 High_mem *bool
172
satayev783195c2021-06-23 21:49:57 +0100173 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700174 Api_levels_annotations_enabled *bool
175
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000176 // Apply the api levels database created by this module rather than generating one in this droidstubs.
177 Api_levels_module *string
178
Colin Cross2207f872021-03-24 12:39:08 -0700179 // the dirs which Metalava extracts API levels annotations from.
180 Api_levels_annotations_dirs []string
181
Cole Faust051fa912022-10-05 12:45:42 -0700182 // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system', 'module-lib' and 'system-server'; defaults to public.
satayev783195c2021-06-23 21:49:57 +0100183 Api_levels_sdk_type *string
184
Colin Cross2207f872021-03-24 12:39:08 -0700185 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
186 Api_levels_jar_filename *string
187
188 // if set to true, collect the values used by the Dev tools and
189 // write them in files packaged with the SDK. Defaults to false.
190 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200191
192 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
193 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
194 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000195
196 // API surface of this module. If set, the module contributes to an API surface.
197 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
198 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000199
200 // a list of aconfig_declarations module names that the stubs generated in this module
201 // depend on.
202 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700203}
204
Anton Hansson52609322021-05-05 10:36:05 +0100205// Used by xsd_config
206type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000207 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100208}
209
210type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000211 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000212}
213
Anton Hansson52609322021-05-05 10:36:05 +0100214// Provider of information about API stubs, used by java_sdk_library.
215type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000216 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100217 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000218 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100219
220 ApiStubsSrcProvider
221}
222
Jihoon Kang063ec002023-06-28 01:16:23 +0000223type currentApiTimestampProvider interface {
224 CurrentApiTimestamp() android.Path
225}
226
Jihoon Kang3c89f042023-12-19 02:40:22 +0000227type annotationFlagsParams struct {
228 migratingNullability bool
229 validatingNullability bool
230 nullabilityWarningsFile android.WritablePath
231 annotationsZip android.WritablePath
232}
233type stubsCommandParams struct {
234 srcJarDir android.ModuleOutPath
235 stubsDir android.OptionalPath
236 stubsSrcJar android.WritablePath
237 metadataZip android.WritablePath
238 metadataDir android.WritablePath
239 apiVersionsXml android.WritablePath
240 nullabilityWarningsFile android.WritablePath
241 annotationsZip android.WritablePath
242 stubConfig stubsCommandConfigParams
243}
244type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000245 stubsType StubsType
246 javaVersion javaVersion
247 deps deps
248 checkApi bool
249 generateStubs bool
250 doApiLint bool
251 doCheckReleased bool
252 writeSdkValues bool
253 migratingNullability bool
254 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000255}
256
Colin Cross2207f872021-03-24 12:39:08 -0700257// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
258// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
259// a droiddoc module to generate documentation.
260func DroidstubsFactory() android.Module {
261 module := &Droidstubs{}
262
263 module.AddProperties(&module.properties,
264 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000265 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700266
267 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000268
269 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
270 module.createApiContribution(ctx)
271 })
Colin Cross2207f872021-03-24 12:39:08 -0700272 return module
273}
274
275// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
276// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
277// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
278// module when symbols needed by the source files are provided by java_library_host modules.
279func DroidstubsHostFactory() android.Module {
280 module := &Droidstubs{}
281
282 module.AddProperties(&module.properties,
283 &module.Javadoc.properties)
284
285 InitDroiddocModule(module, android.HostSupported)
286 return module
287}
288
Jihoon Kang78f89142023-12-27 01:40:29 +0000289func getStubsTypeAndTag(tag string) (StubsType, string, error) {
290 if len(tag) == 0 {
291 return Everything, "", nil
292 }
293 if tag[0] != '.' {
294 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
295 }
296
297 stubsType := Everything
298 // Check if the tag has a stubs type prefix (e.g. ".exportable")
299 for st := Everything; st <= Exportable; st++ {
300 if strings.HasPrefix(tag, "."+st.String()) {
301 stubsType = st
302 }
303 }
304
305 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
306}
307
308// Droidstubs' tag supports specifying with the stubs type.
309// While supporting the pre-existing tags, it also supports tags with
310// the stubs type prefix. Some examples are shown below:
311// {.annotations.zip} - pre-existing behavior. Returns the path to the
312// annotation zip.
313// {.exportable} - Returns the path to the exportable stubs src jar.
314// {.exportable.annotations.zip} - Returns the path to the exportable
315// annotations zip file.
316// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
317// xml file. For unsupported combinations, the default everything output file
318// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700319func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000320 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
321 if err != nil {
322 return nil, err
323 }
324 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700325 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000326 stubsSrcJar, err := d.StubsSrcJar(stubsType)
327 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700328 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000329 docZip, err := d.DocZip(stubsType)
330 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700331 case ".api.txt", android.DefaultDistTag:
332 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000333 apiFilePath, err := d.ApiFilePath(stubsType)
334 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700335 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000336 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
337 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700338 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000339 annotationsZip, err := d.AnnotationsZip(stubsType)
340 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700341 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000342 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
343 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700344 default:
345 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
346 }
347}
348
Jihoon Kang246690a2024-02-01 21:55:01 +0000349func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000350 switch stubsType {
351 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000352 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000353 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000354 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000355 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000356 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000357 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000358 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000359}
360
Jihoon Kang246690a2024-02-01 21:55:01 +0000361func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000362 switch stubsType {
363 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000364 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000365 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000366 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000367 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000368 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000369 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000371 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 }
373 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000374}
375
Jihoon Kang246690a2024-02-01 21:55:01 +0000376func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000377 switch stubsType {
378 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000379 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000380 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000381 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000382 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000383 ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000384 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 if ret == nil && err == nil {
386 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
387 }
388 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000389}
390
Jihoon Kang246690a2024-02-01 21:55:01 +0000391func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000392 switch stubsType {
393 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000394 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000395 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000396 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000397 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000398 if ret == nil && err == nil {
399 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
400 }
401 return ret, err
402}
403
404func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
405 switch stubsType {
406 case Everything:
407 ret, err = d.removedApiFile, nil
408 case Exportable:
409 ret, err = d.exportableRemovedApiFile, nil
410 default:
411 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
412 }
413 if ret == nil && err == nil {
414 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
415 }
416 return ret, err
417}
418
419func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
420 switch stubsType {
421 case Everything:
422 ret, err = d.stubsSrcJar, nil
423 case Exportable:
424 ret, err = d.exportableStubsSrcJar, nil
425 default:
426 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
427 }
428 if ret == nil && err == nil {
429 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
430 }
431 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000432}
433
Jihoon Kang063ec002023-06-28 01:16:23 +0000434func (d *Droidstubs) CurrentApiTimestamp() android.Path {
435 return d.checkCurrentApiTimestamp
436}
437
Colin Cross2207f872021-03-24 12:39:08 -0700438var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
439var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
440var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000441var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000442var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700443
444func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
445 d.Javadoc.addDeps(ctx)
446
447 if len(d.properties.Merge_annotations_dirs) != 0 {
448 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
449 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
450 }
451 }
452
453 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
454 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
455 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
456 }
457 }
458
459 if len(d.properties.Api_levels_annotations_dirs) != 0 {
460 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
461 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
462 }
463 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000464
Jihoon Kang6592e872023-12-19 01:13:16 +0000465 if len(d.properties.Aconfig_declarations) != 0 {
466 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
467 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
468 }
469 }
470
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000471 if d.properties.Api_levels_module != nil {
472 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
473 }
Colin Cross2207f872021-03-24 12:39:08 -0700474}
475
Jihoon Kang3c89f042023-12-19 02:40:22 +0000476func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
477 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
478}
479
480func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000481
Jihoon Kang36c3d962024-03-14 17:28:44 +0000482 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
483 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
484 cmd.FlagWithOutput("--api ", uncheckedApiFile)
485 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000486 if stubsType == Everything {
487 d.apiFile = uncheckedApiFile
488 } else if stubsType == Exportable {
489 d.exportableApiFile = uncheckedApiFile
490 }
Colin Cross2207f872021-03-24 12:39:08 -0700491 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000492 if stubsType == Everything {
493 // If check api is disabled then make the source file available for export.
494 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
495 } else if stubsType == Exportable {
496 d.exportableApiFile = uncheckedApiFile
497 }
Colin Cross2207f872021-03-24 12:39:08 -0700498 }
499
Jihoon Kang36c3d962024-03-14 17:28:44 +0000500 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
501 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
502 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000503 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000504 if stubsType == Everything {
505 d.removedApiFile = uncheckedRemovedFile
506 } else if stubsType == Exportable {
507 d.exportableRemovedApiFile = uncheckedRemovedFile
508 }
Colin Cross2207f872021-03-24 12:39:08 -0700509 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000510 if stubsType == Everything {
511 // If check api is disabled then make the source removed api file available for export.
512 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
513 } else if stubsType == Exportable {
514 d.exportableRemovedApiFile = uncheckedRemovedFile
515 }
Colin Cross2207f872021-03-24 12:39:08 -0700516 }
517
Colin Cross2207f872021-03-24 12:39:08 -0700518 if stubsDir.Valid() {
519 if Bool(d.properties.Create_doc_stubs) {
520 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
521 } else {
522 cmd.FlagWithArg("--stubs ", stubsDir.String())
523 if !Bool(d.properties.Output_javadoc_comments) {
524 cmd.Flag("--exclude-documentation-from-stubs")
525 }
526 }
527 }
528}
529
Jihoon Kang3c89f042023-12-19 02:40:22 +0000530func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000531 if Bool(d.properties.Annotations_enabled) {
532 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100533
Jihoon Kanga11d6792024-03-05 16:12:20 +0000534 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000535 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
536 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000537 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000538
Jihoon Kanga11d6792024-03-05 16:12:20 +0000539 if s := String(d.properties.Validate_nullability_from_list); s != "" {
540 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
541 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000542
Jihoon Kanga11d6792024-03-05 16:12:20 +0000543 if params.validatingNullability {
544 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
545 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000546
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000547 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000548
Jihoon Kanga11d6792024-03-05 16:12:20 +0000549 if len(d.properties.Merge_annotations_dirs) != 0 {
550 d.mergeAnnoDirFlags(ctx, cmd)
551 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000552
Jihoon Kanga11d6792024-03-05 16:12:20 +0000553 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700554 }
Colin Cross2207f872021-03-24 12:39:08 -0700555}
556
557func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
558 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
559 if t, ok := m.(*ExportedDroiddocDir); ok {
560 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
561 } else {
562 ctx.PropertyErrorf("merge_annotations_dirs",
563 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
564 }
565 })
566}
567
568func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
569 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
570 if t, ok := m.(*ExportedDroiddocDir); ok {
571 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
572 } else {
573 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
574 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
575 }
576 })
577}
578
Jihoon Kanga11d6792024-03-05 16:12:20 +0000579func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000580 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000581 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000582 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000583 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000584 } else {
585 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
586 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000587 if stubsType == Everything {
588 apiVersions = s.everythingArtifacts.apiVersionsXml
589 } else if stubsType == Exportable {
590 apiVersions = s.exportableArtifacts.apiVersionsXml
591 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000592 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000593 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000594 } else {
595 ctx.PropertyErrorf("api_levels_module",
596 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
597 }
598 })
Colin Cross2207f872021-03-24 12:39:08 -0700599 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000600 if apiVersions != nil {
601 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
602 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
603 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
604 }
605}
Colin Cross2207f872021-03-24 12:39:08 -0700606
Paul Duffin5a195f42024-05-01 12:52:35 +0100607// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
608// `system-server` directories that contain all the APIs provided by the platform and updatable
609// modules because the `android.jar` files do not. See b/337836752.
610const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
611
Jihoon Kang3c89f042023-12-19 02:40:22 +0000612func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700613 if len(d.properties.Api_levels_annotations_dirs) == 0 {
614 ctx.PropertyErrorf("api_levels_annotations_dirs",
615 "has to be non-empty if api levels annotations was enabled!")
616 }
617
Jihoon Kang3c89f042023-12-19 02:40:22 +0000618 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700619
620 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
621
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100622 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
623 // Add all relevant --android-jar-pattern patterns for Metalava.
624 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
625 // an actual file present on disk (in the order the patterns were passed). For system APIs for
626 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
627 // for older releases. Similarly, module-lib falls back to system API.
628 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100629 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
630 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100631 case "system-server":
632 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
633 case "module-lib":
634 sdkDirs = []string{"module-lib", "system", "public"}
635 case "system":
636 sdkDirs = []string{"system", "public"}
637 case "public":
638 sdkDirs = []string{"public"}
639 default:
640 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
641 return
642 }
643
Paul Duffin92efc612024-05-02 17:18:05 +0100644 // Construct a pattern to match the appropriate extensions that should be included in the
645 // generated api-versions.xml file.
646 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100647 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
648 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100649 // The exception is for system-server which needs to include module-lib and system-server. That
650 // is because while system-server extends module-lib the system-server extension directory only
651 // contains service-* modules which provide system-server APIs it does not list the modules which
652 // only provide a module-lib, so they have to be included separately.
653 extensionSurfacesPattern := sdkDirs[0]
654 if apiLevelsSdkType == "system-server" {
655 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
656 // a pattern that will match either.
657 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
658 }
659 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100660
satayev783195c2021-06-23 21:49:57 +0100661 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200662 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700663 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
664 if t, ok := m.(*ExportedDroiddocDir); ok {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100665 extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200666
667 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
668 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700669 for _, dep := range t.deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100670 // Check to see if it matches an extension first.
671 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200672 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
673 if extensions_dir == "" {
674 extensions_dir = t.dir.String() + "/extensions"
675 }
676 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100677 } else if depBase == filename {
678 // Check to see if it matches a dessert release for an SDK, e.g. Android, Car, Wear, etc..
Colin Cross5f6ffc72021-03-29 21:54:45 -0700679 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100680 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
681 // The output api-versions.xml has been requested to include information on SDK
682 // extensions. That means it also needs to include
683 // so
684 // The module-lib and system-server directories should use `android-plus-updatable.jar`
685 // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
686 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100687 } else if filename != "android.jar" && depBase == "android.jar" {
Colin Cross5f6ffc72021-03-29 21:54:45 -0700688 // Metalava implicitly searches these patterns:
689 // prebuilts/tools/common/api-versions/android-%/android.jar
690 // prebuilts/sdk/%/public/android.jar
691 // Add android.jar files from the api_levels_annotations_dirs directories to try
692 // to satisfy these patterns. If Metalava can't find a match for an API level
693 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700694 cmd.Implicit(dep)
695 }
696 }
satayev783195c2021-06-23 21:49:57 +0100697
698 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700699 } else {
700 ctx.PropertyErrorf("api_levels_annotations_dirs",
701 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
702 }
703 })
satayev783195c2021-06-23 21:49:57 +0100704
Paul Duffin5a195f42024-05-01 12:52:35 +0100705 // Generate the list of --android-jar-pattern options. The order matters so the first one which
706 // matches will be the one that is used for a specific api level..
Pedro Loureirocc203502021-10-04 17:24:00 +0000707 for _, sdkDir := range sdkDirs {
708 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100709 addPattern := func(jarFilename string) {
710 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
711 }
712
713 if sdkDir == "module-lib" || sdkDir == "system-server" {
714 // The module-lib and system-server android.jars do not include the updatable modules (as
715 // doing so in the source would introduce dependency cycles and the prebuilts have to
716 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
717 // that does include the updatable modules and this pattern will match that. This pattern
718 // is added in addition to the following pattern to decouple this change from the change
719 // to add the `android-plus-updatable.jar`.
720 addPattern(AndroidPlusUpdatableJar)
721 }
722
723 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000724 }
satayev783195c2021-06-23 21:49:57 +0100725 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200726
727 if d.properties.Extensions_info_file != nil {
728 if extensions_dir == "" {
729 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
730 }
731 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
732 cmd.Implicit(info_file)
733 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
734 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
735 }
Colin Cross2207f872021-03-24 12:39:08 -0700736}
737
Jihoon Kang472f73f2024-03-28 20:59:29 +0000738func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
739 if len(d.Javadoc.properties.Out) > 0 {
740 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
741 }
742
Jihoon Kang5623e542024-01-31 23:27:26 +0000743 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
744 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000745
Jihoon Kang5623e542024-01-31 23:27:26 +0000746 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
747 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000748
749 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
750 if baselineFile.Valid() {
751 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
752 }
753}
754
Colin Crosse52c2ac2022-03-28 17:03:35 -0700755func metalavaUseRbe(ctx android.ModuleContext) bool {
756 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
757}
758
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000759func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
760 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700761 rule.Command().Text("rm -rf").Flag(homeDir.String())
762 rule.Command().Text("mkdir -p").Flag(homeDir.String())
763
Anton Hansson556e8142021-06-04 16:20:25 +0100764 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700765 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
766
Colin Crosse52c2ac2022-03-28 17:03:35 -0700767 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700768 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700769 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000770 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
771 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700772 labels := map[string]string{"type": "tool", "name": "metalava"}
773 // TODO: metalava pool rejects these jobs
774 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
775 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000776 Labels: labels,
777 ExecStrategy: execStrategy,
778 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
779 Platform: map[string]string{remoteexec.PoolKey: pool},
780 Compare: compare,
781 NumLocalRuns: 1,
782 NumRemoteRuns: 1,
783 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700784 })
Colin Cross2207f872021-03-24 12:39:08 -0700785 }
786
Colin Cross6aa5c402021-03-24 12:28:50 -0700787 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700788 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400789 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000790 FlagWithArg("--java-source ", params.javaVersion.String()).
791 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700792 FlagWithInput("@", srcJarList)
793
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100794 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
795 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000796 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
797 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100798 if len(combinedPaths) > 0 {
799 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700800 }
801
Liz Kammere09e20e2023-10-16 15:07:54 -0400802 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000803
Colin Cross2207f872021-03-24 12:39:08 -0700804 return cmd
805}
806
Jihoon Kang3c89f042023-12-19 02:40:22 +0000807// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
808// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
809// property is defined, apply transformations and only revert the flagged apis that are not
810// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000811func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000812
813 if len(aconfigFlagsPaths) == 0 {
814 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
815 return
816 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000817
818 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
819 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
820
821 var filterArgs string
822 switch stubsType {
823 // No flagged apis specific flags need to be passed to metalava when generating
824 // everything stubs
825 case Everything:
826 return
827
828 case Runtime:
829 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
830
831 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000832 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
833 // the flagged apis that have read_write permissions are exposed on top of the enabled
834 // and read_only apis. This is to support local override of flag values at runtime.
835 if ctx.Config().ReleaseExportRuntimeApis() {
836 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
837 } else {
838 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
839 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000840 }
841
842 ctx.Build(pctx, android.BuildParams{
843 Rule: gatherReleasedFlaggedApisRule,
844 Inputs: aconfigFlagsPaths,
845 Output: releasedFlaggedApisFile,
846 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
847 Args: map[string]string{
848 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
849 "filter_args": filterArgs,
850 },
851 })
852
853 ctx.Build(pctx, android.BuildParams{
854 Rule: generateMetalavaRevertAnnotationsRule,
855 Input: releasedFlaggedApisFile,
856 Output: revertAnnotationsFile,
857 Description: fmt.Sprintf("%s revert annotations", stubsType),
858 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000859
860 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000861}
862
Jihoon Kang3c89f042023-12-19 02:40:22 +0000863func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
864 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700865 if BoolDefault(d.properties.High_mem, false) {
866 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
867 rule.HighMem()
868 }
869
Jihoon Kang3c89f042023-12-19 02:40:22 +0000870 if params.stubConfig.generateStubs {
871 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
872 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700873 }
874
Jihoon Kang3c89f042023-12-19 02:40:22 +0000875 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700876
Jihoon Kang3c89f042023-12-19 02:40:22 +0000877 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000878 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
Colin Cross2207f872021-03-24 12:39:08 -0700879 cmd.Implicits(d.Javadoc.implicits)
880
Jihoon Kang3c89f042023-12-19 02:40:22 +0000881 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700882
Jihoon Kang3c89f042023-12-19 02:40:22 +0000883 if params.stubConfig.writeSdkValues {
884 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
885 }
886
887 annotationParams := annotationFlagsParams{
888 migratingNullability: params.stubConfig.migratingNullability,
889 validatingNullability: params.stubConfig.validatingNullability,
890 nullabilityWarningsFile: params.nullabilityWarningsFile,
891 annotationsZip: params.annotationsZip,
892 }
893
Jihoon Kanga11d6792024-03-05 16:12:20 +0000894 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700895 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000896 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700897
Jihoon Kang472f73f2024-03-28 20:59:29 +0000898 if params.stubConfig.doCheckReleased {
899 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
900 }
901
Colin Crossbc139922021-03-25 18:33:16 -0700902 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700903
Colin Cross2207f872021-03-24 12:39:08 -0700904 for _, o := range d.Javadoc.properties.Out {
905 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
906 }
907
Jihoon Kang3c89f042023-12-19 02:40:22 +0000908 return cmd
909}
Colin Cross2207f872021-03-24 12:39:08 -0700910
Jihoon Kang3c89f042023-12-19 02:40:22 +0000911// Sandbox rule for generating the everything stubs and other artifacts
912func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
913 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
914 rule := android.NewRuleBuilder(pctx, ctx)
915 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
916 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
917 SandboxInputs()
918
919 var stubsDir android.OptionalPath
920 if params.generateStubs {
921 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
922 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
923 }
924
925 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000926 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
927 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000928 }
929
Jihoon Kanga11d6792024-03-05 16:12:20 +0000930 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000931 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000932 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000933 }
Jihoon Kangee113282024-01-23 00:16:41 +0000934 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000935 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000936 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000937 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000938 }
939
940 commonCmdParams := stubsCommandParams{
941 srcJarDir: srcJarDir,
942 stubsDir: stubsDir,
943 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000944 metadataDir: d.everythingArtifacts.metadataDir,
945 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
946 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
947 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000948 stubConfig: params,
949 }
950
951 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
952
953 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
954
955 if params.generateStubs {
956 rule.Command().
957 BuiltTool("soong_zip").
958 Flag("-write_if_changed").
959 Flag("-jar").
960 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
961 FlagWithArg("-C ", stubsDir.String()).
962 FlagWithArg("-D ", stubsDir.String())
963 }
964
965 if params.writeSdkValues {
966 rule.Command().
967 BuiltTool("soong_zip").
968 Flag("-write_if_changed").
969 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000970 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
971 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
972 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000973 }
974
975 // TODO: We don't really need two separate API files, but this is a reminiscence of how
976 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
977 if params.doApiLint {
978 rule.Command().Text("touch").Output(d.apiLintTimestamp)
979 }
980 if params.doCheckReleased {
981 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
982 }
983
984 // TODO(b/183630617): rewrapper doesn't support restat rules
985 if !metalavaUseRbe(ctx) {
986 rule.Restat()
987 }
988
989 zipSyncCleanupCmd(rule, srcJarDir)
990
991 rule.Build("metalava", "metalava merged")
992}
993
994// Sandbox rule for generating the everything artifacts that are not run by
995// default but only run based on the module configurations
996func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700997
998 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000999 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +00001000 var newSince android.Paths
1001 if d.properties.Check_api.Api_lint.New_since != nil {
1002 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
1003 }
Paul Duffin0a71d732024-04-22 13:22:56 +01001004 cmd.Flag("--api-lint")
1005 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001006 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001007 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
1008
Colin Cross0d532412021-03-25 09:38:45 -07001009 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -07001010 if d.Name() != "android.car-system-stubs-docs" &&
1011 d.Name() != "android.car-stubs-docs" {
1012 cmd.Flag("--lints-as-errors")
1013 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
1014 }
1015
1016 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001017 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
1018 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001019
1020 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -07001021 //
1022 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
1023 // message and metalava's one?
1024 msg := `$'` + // Enclose with $' ... '
1025 `************************************************************\n` +
1026 `Your API changes are triggering API Lint warnings or errors.\n` +
1027 `To make these errors go away, fix the code according to the\n` +
1028 `error and/or warning messages above.\n` +
1029 `\n` +
1030 `If it is not possible to do so, there are workarounds:\n` +
1031 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +00001032 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
1033 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -07001034
1035 if baselineFile.Valid() {
1036 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1037 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
1038
1039 msg += fmt.Sprintf(``+
1040 `2. You can update the baseline by executing the following\n`+
1041 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -07001042 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
1043 ` "%s" \\\n`+
1044 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001045 ` To submit the revised baseline.txt to the main Android\n`+
1046 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
1047 } else {
1048 msg += fmt.Sprintf(``+
1049 `2. You can add a baseline file of existing lint failures\n`+
1050 ` to the build rule of %s.\n`, d.Name())
1051 }
1052 // Note the message ends with a ' (single quote), to close the $' ... ' .
1053 msg += `************************************************************\n'`
1054
1055 cmd.FlagWithArg("--error-message:api-lint ", msg)
1056 }
1057
1058 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001059 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001060 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001061 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001062 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001063 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001064 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1065 }
Colin Cross2207f872021-03-24 12:39:08 -07001066 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1067 msg := `$'\n******************************\n` +
1068 `You have tried to change the API from what has been previously released in\n` +
1069 `an SDK. Please fix the errors listed above.\n` +
1070 `******************************\n'`
1071
1072 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1073 }
1074
Paul Duffin10a23c22023-08-11 22:47:31 +01001075 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1076 // Pass the current API file into metalava so it can use it as the basis for determining how to
1077 // generate the output signature files (both api and removed).
1078 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1079 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1080 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001081}
Paul Duffin10a23c22023-08-11 22:47:31 +01001082
Jihoon Kang3c89f042023-12-19 02:40:22 +00001083// Sandbox rule for generating exportable stubs and other artifacts
1084func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1085 optionalCmdParams := stubsCommandParams{
1086 stubConfig: params,
1087 }
1088
Jihoon Kang246690a2024-02-01 21:55:01 +00001089 if params.generateStubs {
1090 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1091 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1092 }
1093
Jihoon Kang3c89f042023-12-19 02:40:22 +00001094 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001095 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1096 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1097 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1098 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001099 }
1100
Jihoon Kanga11d6792024-03-05 16:12:20 +00001101 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001102 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001103 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1104 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001105 }
Jihoon Kangee113282024-01-23 00:16:41 +00001106 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1107 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001108 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001109 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001110 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1111 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001112 }
1113
1114 if params.checkApi || String(d.properties.Api_filename) != "" {
1115 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1116 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1117 }
1118
1119 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1120 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1121 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1122 }
1123
1124 d.optionalStubCmd(ctx, optionalCmdParams)
1125}
1126
1127func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1128
1129 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1130 rule := android.NewRuleBuilder(pctx, ctx)
1131 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1132 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1133 SandboxInputs()
1134
1135 if params.stubConfig.generateStubs {
1136 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1137 }
1138
1139 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1140
Jihoon Kang5d701272024-02-15 21:53:49 +00001141 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001142
1143 if params.stubConfig.doApiLint {
1144 // Pass the lint baseline file as an input to resolve the lint errors.
1145 // The exportable stubs generation does not update the lint baseline file.
1146 // Lint baseline file update is handled by the everything stubs
1147 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1148 if baselineFile.Valid() {
1149 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1150 }
1151 }
1152
1153 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001154 rule.Command().
1155 BuiltTool("soong_zip").
1156 Flag("-write_if_changed").
1157 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001158 FlagWithOutput("-o ", params.stubsSrcJar).
1159 FlagWithArg("-C ", params.stubsDir.String()).
1160 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001161 }
1162
Jihoon Kang3c89f042023-12-19 02:40:22 +00001163 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001164 rule.Command().
1165 BuiltTool("soong_zip").
1166 Flag("-write_if_changed").
1167 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001168 FlagWithOutput("-o ", params.metadataZip).
1169 FlagWithArg("-C ", params.metadataDir.String()).
1170 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001171 }
1172
Colin Cross6aa5c402021-03-24 12:28:50 -07001173 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001174 if !metalavaUseRbe(ctx) {
1175 rule.Restat()
1176 }
Colin Cross2207f872021-03-24 12:39:08 -07001177
Jihoon Kang3c89f042023-12-19 02:40:22 +00001178 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001179
Jihoon Kang3c89f042023-12-19 02:40:22 +00001180 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1181}
1182
1183func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1184 deps := d.Javadoc.collectDeps(ctx)
1185
1186 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1187 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1188
1189 // Add options for the other optional tasks: API-lint and check-released.
1190 // We generate separate timestamp files for them.
1191 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1192 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1193
1194 writeSdkValues := Bool(d.properties.Write_sdk_values)
1195
1196 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1197
1198 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1199 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1200 String(d.properties.Validate_nullability_from_list) != "")
1201
1202 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1203 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1204
1205 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001206 javaVersion: javaVersion,
1207 deps: deps,
1208 checkApi: checkApi,
1209 generateStubs: generateStubs,
1210 doApiLint: doApiLint,
1211 doCheckReleased: doCheckReleased,
1212 writeSdkValues: writeSdkValues,
1213 migratingNullability: migratingNullability,
1214 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001215 }
1216 stubCmdParams.stubsType = Everything
1217 // Create default (i.e. "everything" stubs) rule for metalava
1218 d.everythingStubCmd(ctx, stubCmdParams)
1219
Jihoon Kangd40c5912024-03-05 16:12:20 +00001220 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001221 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1222 // strips all flagged apis to generate the "exportable" stubs
1223 stubCmdParams.stubsType = Exportable
1224 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001225
Paul Duffine7a86642022-08-16 15:43:20 +00001226 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1227
1228 if len(d.Javadoc.properties.Out) > 0 {
1229 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1230 }
1231
1232 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1233 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1234 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1235
1236 if baselineFile.Valid() {
1237 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1238 }
1239
Jihoon Kang3c89f042023-12-19 02:40:22 +00001240 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001241
1242 rule := android.NewRuleBuilder(pctx, ctx)
1243
1244 // Diff command line.
1245 // -F matches the closest "opening" line, such as "package android {"
1246 // and " public class Intent {".
1247 diff := `diff -u -F '{ *$'`
1248
1249 rule.Command().Text("( true")
1250 rule.Command().
1251 Text(diff).
1252 Input(apiFile).Input(d.apiFile)
1253
1254 rule.Command().
1255 Text(diff).
1256 Input(removedApiFile).Input(d.removedApiFile)
1257
1258 msg := fmt.Sprintf(`\n******************************\n`+
1259 `You have tried to change the API from what has been previously approved.\n\n`+
1260 `To make these errors go away, you have two choices:\n`+
1261 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1262 ` to the new methods, etc. shown in the above diff.\n\n`+
1263 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1264 ` m %s-update-current-api\n\n`+
1265 ` To submit the revised current.txt to the main Android repository,\n`+
1266 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001267 `If your build failed due to stub validation, you can resolve the errors with\n`+
1268 `either of the two choices above and try re-building the target.\n`+
1269 `If the mismatch between the stubs and the current.txt is intended,\n`+
1270 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001271 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1272 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001273 `******************************\n`, ctx.ModuleName())
1274
1275 rule.Command().
1276 Text("touch").Output(d.checkCurrentApiTimestamp).
1277 Text(") || (").
1278 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1279 Text("; exit 38").
1280 Text(")")
1281
1282 rule.Build("metalavaCurrentApiCheck", "check current API")
1283
Jihoon Kang3c89f042023-12-19 02:40:22 +00001284 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001285
1286 // update API rule
1287 rule = android.NewRuleBuilder(pctx, ctx)
1288
1289 rule.Command().Text("( true")
1290
1291 rule.Command().
1292 Text("cp").Flag("-f").
1293 Input(d.apiFile).Flag(apiFile.String())
1294
1295 rule.Command().
1296 Text("cp").Flag("-f").
1297 Input(d.removedApiFile).Flag(removedApiFile.String())
1298
1299 msg = "failed to update public API"
1300
1301 rule.Command().
1302 Text("touch").Output(d.updateCurrentApiTimestamp).
1303 Text(") || (").
1304 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1305 Text("; exit 38").
1306 Text(")")
1307
1308 rule.Build("metalavaCurrentApiUpdate", "update current API")
1309 }
1310
Colin Cross2207f872021-03-24 12:39:08 -07001311 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001312 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001313 ctx.PropertyErrorf("check_nullability_warnings",
1314 "Cannot specify check_nullability_warnings unless validating nullability")
1315 }
1316
1317 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1318
Jihoon Kang3c89f042023-12-19 02:40:22 +00001319 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001320
1321 msg := fmt.Sprintf(`\n******************************\n`+
1322 `The warnings encountered during nullability annotation validation did\n`+
1323 `not match the checked in file of expected warnings. The diffs are shown\n`+
1324 `above. You have two options:\n`+
1325 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1326 ` 2. Update the file of expected warnings by running:\n`+
1327 ` cp %s %s\n`+
1328 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001329 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001330
1331 rule := android.NewRuleBuilder(pctx, ctx)
1332
1333 rule.Command().
1334 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001335 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001336 Text("&&").
1337 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1338 Text(") || (").
1339 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1340 Text("; exit 38").
1341 Text(")")
1342
1343 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1344 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001345 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001346}
1347
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001348func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1349 api_file := d.properties.Check_api.Current.Api_file
1350 api_surface := d.properties.Api_surface
1351
1352 props := struct {
1353 Name *string
1354 Api_surface *string
1355 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001356 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001357 }{}
1358
1359 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1360 props.Api_surface = api_surface
1361 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001362 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001363
1364 ctx.CreateModule(ApiContributionFactory, &props)
1365}
1366
Spandan Das0b555e32022-11-28 18:48:51 +00001367// TODO (b/262014796): Export the API contributions of CorePlatformApi
1368// A map to populate the api surface of a droidstub from a substring appearing in its name
1369// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1370// use a strict naming convention
1371var (
1372 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001373 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001374 "intracore": android.SdkIntraCore,
1375 "intra.core": android.SdkIntraCore,
1376 "system_server": android.SdkSystemServer,
1377 "system-server": android.SdkSystemServer,
1378 "system": android.SdkSystem,
1379 "module_lib": android.SdkModule,
1380 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001381 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001382 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001383 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001384 }
1385)
1386
Colin Cross2207f872021-03-24 12:39:08 -07001387func StubsDefaultsFactory() android.Module {
1388 module := &DocDefaults{}
1389
1390 module.AddProperties(
1391 &JavadocProperties{},
1392 &DroidstubsProperties{},
1393 )
1394
1395 android.InitDefaultsModule(module)
1396
1397 return module
1398}
1399
1400var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1401
1402type PrebuiltStubsSourcesProperties struct {
1403 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001404
1405 // Name of the source soong module that gets shadowed by this prebuilt
1406 // If unspecified, follows the naming convention that the source module of
1407 // the prebuilt is Name() without "prebuilt_" prefix
1408 Source_module_name *string
1409
1410 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1411 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1412 // (without any prebuilt_ prefix)
1413 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1414}
1415
1416func (j *PrebuiltStubsSources) BaseModuleName() string {
1417 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1418}
1419
1420func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1421 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001422}
1423
1424type PrebuiltStubsSources struct {
1425 android.ModuleBase
1426 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001427 embeddableInModuleAndImport
1428
Colin Cross2207f872021-03-24 12:39:08 -07001429 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001430
1431 properties PrebuiltStubsSourcesProperties
1432
kgui67007242022-01-25 13:50:25 +08001433 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001434}
1435
1436func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1437 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001438 // prebuilt droidstubs does not output "exportable" stubs.
1439 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1440 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001441 return android.Paths{p.stubsSrcJar}, nil
1442 default:
1443 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1444 }
1445}
1446
Jihoon Kangee113282024-01-23 00:16:41 +00001447func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1448 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001449}
1450
1451func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001452 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001453 ctx.PropertyErrorf("srcs", "must only specify one directory path or srcjar, contains %d paths", len(p.properties.Srcs))
Colin Cross2207f872021-03-24 12:39:08 -07001454 return
1455 }
1456
Anton Hansson86758ac2021-11-03 14:44:12 +00001457 src := p.properties.Srcs[0]
1458 if filepath.Ext(src) == ".srcjar" {
1459 // This is a srcjar. We can use it directly.
1460 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1461 } else {
1462 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001463
Anton Hansson86758ac2021-11-03 14:44:12 +00001464 // This is a directory. Glob the contents just in case the directory does not exist.
1465 srcGlob := src + "/**/*"
1466 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001467
Anton Hansson86758ac2021-11-03 14:44:12 +00001468 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1469 // the path components are invalid it won't in this case because no components
1470 // are specified and the module directory must exist in order to get this far.
1471 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001472
Anton Hansson86758ac2021-11-03 14:44:12 +00001473 rule := android.NewRuleBuilder(pctx, ctx)
1474 rule.Command().
1475 BuiltTool("soong_zip").
1476 Flag("-write_if_changed").
1477 Flag("-jar").
1478 FlagWithOutput("-o ", outPath).
1479 FlagWithArg("-C ", srcDir.String()).
1480 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1481 rule.Restat()
1482 rule.Build("zip src", "Create srcjar from prebuilt source")
1483 p.stubsSrcJar = outPath
1484 }
Colin Cross2207f872021-03-24 12:39:08 -07001485}
1486
1487func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1488 return &p.prebuilt
1489}
1490
1491func (p *PrebuiltStubsSources) Name() string {
1492 return p.prebuilt.Name(p.ModuleBase.Name())
1493}
1494
1495// prebuilt_stubs_sources imports a set of java source files as if they were
1496// generated by droidstubs.
1497//
1498// By default, a prebuilt_stubs_sources has a single variant that expects a
1499// set of `.java` files generated by droidstubs.
1500//
1501// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1502// for host modules.
1503//
1504// Intended only for use by sdk snapshots.
1505func PrebuiltStubsSourcesFactory() android.Module {
1506 module := &PrebuiltStubsSources{}
1507
1508 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001509 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001510
1511 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001512 InitDroiddocModule(module, android.HostAndDeviceSupported)
1513 return module
1514}