blob: 01571858cf447c772f27d1be8b5d8e1d34804097 [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
Jihoon Kangee113282024-01-23 00:16:41 +0000109 exportableApiFile android.WritablePath
110 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700111}
112
113type DroidstubsProperties struct {
114 // The generated public API filename by Metalava, defaults to <module>_api.txt
115 Api_filename *string
116
117 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
118 Removed_api_filename *string
119
Colin Cross2207f872021-03-24 12:39:08 -0700120 Check_api struct {
121 Last_released ApiToCheck
122
123 Current ApiToCheck
124
125 Api_lint struct {
126 Enabled *bool
127
128 // If set, performs api_lint on any new APIs not found in the given signature file
129 New_since *string `android:"path"`
130
131 // If not blank, path to the baseline txt file for approved API lint violations.
132 Baseline_file *string `android:"path"`
133 }
134 }
135
136 // user can specify the version of previous released API file in order to do compatibility check.
137 Previous_api *string `android:"path"`
138
139 // is set to true, Metalava will allow framework SDK to contain annotations.
140 Annotations_enabled *bool
141
142 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
143 Merge_annotations_dirs []string
144
145 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
146 Merge_inclusion_annotations_dirs []string
147
148 // a file containing a list of classes to do nullability validation for.
149 Validate_nullability_from_list *string
150
151 // a file containing expected warnings produced by validation of nullability annotations.
152 Check_nullability_warnings *string
153
154 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
155 Create_doc_stubs *bool
156
157 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
158 // Has no effect if create_doc_stubs: true.
159 Output_javadoc_comments *bool
160
161 // if set to false then do not write out stubs. Defaults to true.
162 //
163 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
164 Generate_stubs *bool
165
166 // 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 -0400167 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700168 High_mem *bool
169
satayev783195c2021-06-23 21:49:57 +0100170 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700171 Api_levels_annotations_enabled *bool
172
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000173 // Apply the api levels database created by this module rather than generating one in this droidstubs.
174 Api_levels_module *string
175
Colin Cross2207f872021-03-24 12:39:08 -0700176 // the dirs which Metalava extracts API levels annotations from.
177 Api_levels_annotations_dirs []string
178
Cole Faust051fa912022-10-05 12:45:42 -0700179 // 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 +0100180 Api_levels_sdk_type *string
181
Colin Cross2207f872021-03-24 12:39:08 -0700182 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
183 Api_levels_jar_filename *string
184
185 // if set to true, collect the values used by the Dev tools and
186 // write them in files packaged with the SDK. Defaults to false.
187 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200188
189 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
190 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
191 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000192
193 // API surface of this module. If set, the module contributes to an API surface.
194 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
195 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000196
197 // a list of aconfig_declarations module names that the stubs generated in this module
198 // depend on.
199 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700200}
201
Anton Hansson52609322021-05-05 10:36:05 +0100202// Used by xsd_config
203type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000204 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100205}
206
207type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000208 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000209}
210
Anton Hansson52609322021-05-05 10:36:05 +0100211// Provider of information about API stubs, used by java_sdk_library.
212type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000213 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100214 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000215 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100216
217 ApiStubsSrcProvider
218}
219
Jihoon Kang063ec002023-06-28 01:16:23 +0000220type currentApiTimestampProvider interface {
221 CurrentApiTimestamp() android.Path
222}
223
Jihoon Kang3c89f042023-12-19 02:40:22 +0000224type annotationFlagsParams struct {
225 migratingNullability bool
226 validatingNullability bool
227 nullabilityWarningsFile android.WritablePath
228 annotationsZip android.WritablePath
229}
230type stubsCommandParams struct {
231 srcJarDir android.ModuleOutPath
232 stubsDir android.OptionalPath
233 stubsSrcJar android.WritablePath
234 metadataZip android.WritablePath
235 metadataDir android.WritablePath
236 apiVersionsXml android.WritablePath
237 nullabilityWarningsFile android.WritablePath
238 annotationsZip android.WritablePath
239 stubConfig stubsCommandConfigParams
240}
241type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000242 stubsType StubsType
243 javaVersion javaVersion
244 deps deps
245 checkApi bool
246 generateStubs bool
247 doApiLint bool
248 doCheckReleased bool
249 writeSdkValues bool
250 migratingNullability bool
251 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000252}
253
Colin Cross2207f872021-03-24 12:39:08 -0700254// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
255// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
256// a droiddoc module to generate documentation.
257func DroidstubsFactory() android.Module {
258 module := &Droidstubs{}
259
260 module.AddProperties(&module.properties,
261 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000262 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700263
264 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000265
266 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
267 module.createApiContribution(ctx)
268 })
Colin Cross2207f872021-03-24 12:39:08 -0700269 return module
270}
271
272// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
273// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
274// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
275// module when symbols needed by the source files are provided by java_library_host modules.
276func DroidstubsHostFactory() android.Module {
277 module := &Droidstubs{}
278
279 module.AddProperties(&module.properties,
280 &module.Javadoc.properties)
281
282 InitDroiddocModule(module, android.HostSupported)
283 return module
284}
285
Jihoon Kang78f89142023-12-27 01:40:29 +0000286func getStubsTypeAndTag(tag string) (StubsType, string, error) {
287 if len(tag) == 0 {
288 return Everything, "", nil
289 }
290 if tag[0] != '.' {
291 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
292 }
293
294 stubsType := Everything
295 // Check if the tag has a stubs type prefix (e.g. ".exportable")
296 for st := Everything; st <= Exportable; st++ {
297 if strings.HasPrefix(tag, "."+st.String()) {
298 stubsType = st
299 }
300 }
301
302 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
303}
304
305// Droidstubs' tag supports specifying with the stubs type.
306// While supporting the pre-existing tags, it also supports tags with
307// the stubs type prefix. Some examples are shown below:
308// {.annotations.zip} - pre-existing behavior. Returns the path to the
309// annotation zip.
310// {.exportable} - Returns the path to the exportable stubs src jar.
311// {.exportable.annotations.zip} - Returns the path to the exportable
312// annotations zip file.
313// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
314// xml file. For unsupported combinations, the default everything output file
315// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700316func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000317 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
318 if err != nil {
319 return nil, err
320 }
321 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700322 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000323 stubsSrcJar, err := d.StubsSrcJar(stubsType)
324 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700325 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000326 docZip, err := d.DocZip(stubsType)
327 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700328 case ".api.txt", android.DefaultDistTag:
329 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000330 apiFilePath, err := d.ApiFilePath(stubsType)
331 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700332 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000333 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
334 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700335 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000336 annotationsZip, err := d.AnnotationsZip(stubsType)
337 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700338 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000339 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
340 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700341 default:
342 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
343 }
344}
345
Jihoon Kang246690a2024-02-01 21:55:01 +0000346func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000347 switch stubsType {
348 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000349 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000350 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000351 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000352 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000353 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000354 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000355 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000356}
357
Jihoon Kang246690a2024-02-01 21:55:01 +0000358func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000359 switch stubsType {
360 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000361 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000362 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000363 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000364 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000365 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000366 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000367 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000368 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000369 }
370 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000371}
372
Jihoon Kang246690a2024-02-01 21:55:01 +0000373func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000374 switch stubsType {
375 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000376 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000377 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000378 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000379 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000380 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 +0000381 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000382 if ret == nil && err == nil {
383 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
384 }
385 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000386}
387
Jihoon Kang246690a2024-02-01 21:55:01 +0000388func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000389 switch stubsType {
390 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000391 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000392 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000393 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000394 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000395 if ret == nil && err == nil {
396 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
397 }
398 return ret, err
399}
400
401func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
402 switch stubsType {
403 case Everything:
404 ret, err = d.removedApiFile, nil
405 case Exportable:
406 ret, err = d.exportableRemovedApiFile, nil
407 default:
408 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
409 }
410 if ret == nil && err == nil {
411 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
412 }
413 return ret, err
414}
415
416func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
417 switch stubsType {
418 case Everything:
419 ret, err = d.stubsSrcJar, nil
420 case Exportable:
421 ret, err = d.exportableStubsSrcJar, nil
422 default:
423 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
424 }
425 if ret == nil && err == nil {
426 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
427 }
428 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000429}
430
Jihoon Kang063ec002023-06-28 01:16:23 +0000431func (d *Droidstubs) CurrentApiTimestamp() android.Path {
432 return d.checkCurrentApiTimestamp
433}
434
Colin Cross2207f872021-03-24 12:39:08 -0700435var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
436var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
437var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000438var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000439var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700440
441func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
442 d.Javadoc.addDeps(ctx)
443
444 if len(d.properties.Merge_annotations_dirs) != 0 {
445 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
446 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
447 }
448 }
449
450 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
451 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
452 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
453 }
454 }
455
456 if len(d.properties.Api_levels_annotations_dirs) != 0 {
457 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
458 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
459 }
460 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000461
Jihoon Kang6592e872023-12-19 01:13:16 +0000462 if len(d.properties.Aconfig_declarations) != 0 {
463 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
464 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
465 }
466 }
467
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000468 if d.properties.Api_levels_module != nil {
469 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
470 }
Colin Cross2207f872021-03-24 12:39:08 -0700471}
472
Jihoon Kang3c89f042023-12-19 02:40:22 +0000473func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
474 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
475}
476
477func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000478
Jihoon Kang36c3d962024-03-14 17:28:44 +0000479 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
480 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
481 cmd.FlagWithOutput("--api ", uncheckedApiFile)
482 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000483 if stubsType == Everything {
484 d.apiFile = uncheckedApiFile
485 } else if stubsType == Exportable {
486 d.exportableApiFile = uncheckedApiFile
487 }
Colin Cross2207f872021-03-24 12:39:08 -0700488 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000489 if stubsType == Everything {
490 // If check api is disabled then make the source file available for export.
491 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
492 } else if stubsType == Exportable {
493 d.exportableApiFile = uncheckedApiFile
494 }
Colin Cross2207f872021-03-24 12:39:08 -0700495 }
496
Jihoon Kang36c3d962024-03-14 17:28:44 +0000497 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
498 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
499 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000500 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000501 if stubsType == Everything {
502 d.removedApiFile = uncheckedRemovedFile
503 } else if stubsType == Exportable {
504 d.exportableRemovedApiFile = uncheckedRemovedFile
505 }
Colin Cross2207f872021-03-24 12:39:08 -0700506 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000507 if stubsType == Everything {
508 // If check api is disabled then make the source removed api file available for export.
509 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
510 } else if stubsType == Exportable {
511 d.exportableRemovedApiFile = uncheckedRemovedFile
512 }
Colin Cross2207f872021-03-24 12:39:08 -0700513 }
514
Colin Cross2207f872021-03-24 12:39:08 -0700515 if stubsDir.Valid() {
516 if Bool(d.properties.Create_doc_stubs) {
517 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
518 } else {
519 cmd.FlagWithArg("--stubs ", stubsDir.String())
520 if !Bool(d.properties.Output_javadoc_comments) {
521 cmd.Flag("--exclude-documentation-from-stubs")
522 }
523 }
524 }
525}
526
Jihoon Kang3c89f042023-12-19 02:40:22 +0000527func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000528 if Bool(d.properties.Annotations_enabled) {
529 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100530
Jihoon Kanga11d6792024-03-05 16:12:20 +0000531 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000532 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
533 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000534 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000535
Jihoon Kanga11d6792024-03-05 16:12:20 +0000536 if s := String(d.properties.Validate_nullability_from_list); s != "" {
537 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
538 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000539
Jihoon Kanga11d6792024-03-05 16:12:20 +0000540 if params.validatingNullability {
541 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
542 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000543
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000544 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000545
Jihoon Kanga11d6792024-03-05 16:12:20 +0000546 if len(d.properties.Merge_annotations_dirs) != 0 {
547 d.mergeAnnoDirFlags(ctx, cmd)
548 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000549
Jihoon Kanga11d6792024-03-05 16:12:20 +0000550 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700551 }
Colin Cross2207f872021-03-24 12:39:08 -0700552}
553
554func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
555 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
556 if t, ok := m.(*ExportedDroiddocDir); ok {
557 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
558 } else {
559 ctx.PropertyErrorf("merge_annotations_dirs",
560 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
561 }
562 })
563}
564
565func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
566 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
567 if t, ok := m.(*ExportedDroiddocDir); ok {
568 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
569 } else {
570 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
571 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
572 }
573 })
574}
575
Jihoon Kanga11d6792024-03-05 16:12:20 +0000576func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000577 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000578 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000579 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000580 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000581 } else {
582 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
583 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000584 if stubsType == Everything {
585 apiVersions = s.everythingArtifacts.apiVersionsXml
586 } else if stubsType == Exportable {
587 apiVersions = s.exportableArtifacts.apiVersionsXml
588 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000589 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000590 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000591 } else {
592 ctx.PropertyErrorf("api_levels_module",
593 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
594 }
595 })
Colin Cross2207f872021-03-24 12:39:08 -0700596 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000597 if apiVersions != nil {
598 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
599 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
600 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
601 }
602}
Colin Cross2207f872021-03-24 12:39:08 -0700603
Paul Duffin5a195f42024-05-01 12:52:35 +0100604// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
605// `system-server` directories that contain all the APIs provided by the platform and updatable
606// modules because the `android.jar` files do not. See b/337836752.
607const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
608
Jihoon Kang3c89f042023-12-19 02:40:22 +0000609func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700610 if len(d.properties.Api_levels_annotations_dirs) == 0 {
611 ctx.PropertyErrorf("api_levels_annotations_dirs",
612 "has to be non-empty if api levels annotations was enabled!")
613 }
614
Jihoon Kang3c89f042023-12-19 02:40:22 +0000615 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700616
617 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
618
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100619 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
620 // Add all relevant --android-jar-pattern patterns for Metalava.
621 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
622 // an actual file present on disk (in the order the patterns were passed). For system APIs for
623 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
624 // for older releases. Similarly, module-lib falls back to system API.
625 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100626 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
627 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100628 case "system-server":
629 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
630 case "module-lib":
631 sdkDirs = []string{"module-lib", "system", "public"}
632 case "system":
633 sdkDirs = []string{"system", "public"}
634 case "public":
635 sdkDirs = []string{"public"}
636 default:
637 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
638 return
639 }
640
Paul Duffin92efc612024-05-02 17:18:05 +0100641 // Construct a pattern to match the appropriate extensions that should be included in the
642 // generated api-versions.xml file.
643 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100644 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
645 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100646 // The exception is for system-server which needs to include module-lib and system-server. That
647 // is because while system-server extends module-lib the system-server extension directory only
648 // contains service-* modules which provide system-server APIs it does not list the modules which
649 // only provide a module-lib, so they have to be included separately.
650 extensionSurfacesPattern := sdkDirs[0]
651 if apiLevelsSdkType == "system-server" {
652 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
653 // a pattern that will match either.
654 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
655 }
656 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100657
satayev783195c2021-06-23 21:49:57 +0100658 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200659 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700660 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
661 if t, ok := m.(*ExportedDroiddocDir); ok {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100662 extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200663
664 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
665 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700666 for _, dep := range t.deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100667 // Check to see if it matches an extension first.
668 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200669 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
670 if extensions_dir == "" {
671 extensions_dir = t.dir.String() + "/extensions"
672 }
673 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100674 } else if depBase == filename {
675 // 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 -0700676 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100677 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
678 // The output api-versions.xml has been requested to include information on SDK
679 // extensions. That means it also needs to include
680 // so
681 // The module-lib and system-server directories should use `android-plus-updatable.jar`
682 // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
683 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100684 } else if filename != "android.jar" && depBase == "android.jar" {
Colin Cross5f6ffc72021-03-29 21:54:45 -0700685 // Metalava implicitly searches these patterns:
686 // prebuilts/tools/common/api-versions/android-%/android.jar
687 // prebuilts/sdk/%/public/android.jar
688 // Add android.jar files from the api_levels_annotations_dirs directories to try
689 // to satisfy these patterns. If Metalava can't find a match for an API level
690 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700691 cmd.Implicit(dep)
692 }
693 }
satayev783195c2021-06-23 21:49:57 +0100694
695 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700696 } else {
697 ctx.PropertyErrorf("api_levels_annotations_dirs",
698 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
699 }
700 })
satayev783195c2021-06-23 21:49:57 +0100701
Paul Duffin5a195f42024-05-01 12:52:35 +0100702 // Generate the list of --android-jar-pattern options. The order matters so the first one which
703 // matches will be the one that is used for a specific api level..
Pedro Loureirocc203502021-10-04 17:24:00 +0000704 for _, sdkDir := range sdkDirs {
705 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100706 addPattern := func(jarFilename string) {
707 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, jarFilename))
708 }
709
710 if sdkDir == "module-lib" || sdkDir == "system-server" {
711 // The module-lib and system-server android.jars do not include the updatable modules (as
712 // doing so in the source would introduce dependency cycles and the prebuilts have to
713 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
714 // that does include the updatable modules and this pattern will match that. This pattern
715 // is added in addition to the following pattern to decouple this change from the change
716 // to add the `android-plus-updatable.jar`.
717 addPattern(AndroidPlusUpdatableJar)
718 }
719
720 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000721 }
satayev783195c2021-06-23 21:49:57 +0100722 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200723
724 if d.properties.Extensions_info_file != nil {
725 if extensions_dir == "" {
726 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
727 }
728 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
729 cmd.Implicit(info_file)
730 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
731 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
732 }
Colin Cross2207f872021-03-24 12:39:08 -0700733}
734
Jihoon Kang472f73f2024-03-28 20:59:29 +0000735func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
736 if len(d.Javadoc.properties.Out) > 0 {
737 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
738 }
739
Jihoon Kang5623e542024-01-31 23:27:26 +0000740 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
741 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000742
Jihoon Kang5623e542024-01-31 23:27:26 +0000743 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
744 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000745
746 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
747 if baselineFile.Valid() {
748 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
749 }
750}
751
Colin Crosse52c2ac2022-03-28 17:03:35 -0700752func metalavaUseRbe(ctx android.ModuleContext) bool {
753 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
754}
755
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000756func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
757 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700758 rule.Command().Text("rm -rf").Flag(homeDir.String())
759 rule.Command().Text("mkdir -p").Flag(homeDir.String())
760
Anton Hansson556e8142021-06-04 16:20:25 +0100761 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700762 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
763
Colin Crosse52c2ac2022-03-28 17:03:35 -0700764 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700765 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700766 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000767 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
768 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700769 labels := map[string]string{"type": "tool", "name": "metalava"}
770 // TODO: metalava pool rejects these jobs
771 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
772 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000773 Labels: labels,
774 ExecStrategy: execStrategy,
775 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
776 Platform: map[string]string{remoteexec.PoolKey: pool},
777 Compare: compare,
778 NumLocalRuns: 1,
779 NumRemoteRuns: 1,
780 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700781 })
Colin Cross2207f872021-03-24 12:39:08 -0700782 }
783
Colin Cross6aa5c402021-03-24 12:28:50 -0700784 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700785 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400786 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000787 FlagWithArg("--java-source ", params.javaVersion.String()).
788 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700789 FlagWithInput("@", srcJarList)
790
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100791 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
792 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000793 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
794 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100795 if len(combinedPaths) > 0 {
796 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700797 }
798
Liz Kammere09e20e2023-10-16 15:07:54 -0400799 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000800
Colin Cross2207f872021-03-24 12:39:08 -0700801 return cmd
802}
803
Jihoon Kang3c89f042023-12-19 02:40:22 +0000804// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
805// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
806// property is defined, apply transformations and only revert the flagged apis that are not
807// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000808func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000809
810 if len(aconfigFlagsPaths) == 0 {
811 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
812 return
813 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000814
815 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
816 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
817
818 var filterArgs string
819 switch stubsType {
820 // No flagged apis specific flags need to be passed to metalava when generating
821 // everything stubs
822 case Everything:
823 return
824
825 case Runtime:
826 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
827
828 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000829 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
830 // the flagged apis that have read_write permissions are exposed on top of the enabled
831 // and read_only apis. This is to support local override of flag values at runtime.
832 if ctx.Config().ReleaseExportRuntimeApis() {
833 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
834 } else {
835 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
836 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000837 }
838
839 ctx.Build(pctx, android.BuildParams{
840 Rule: gatherReleasedFlaggedApisRule,
841 Inputs: aconfigFlagsPaths,
842 Output: releasedFlaggedApisFile,
843 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
844 Args: map[string]string{
845 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
846 "filter_args": filterArgs,
847 },
848 })
849
850 ctx.Build(pctx, android.BuildParams{
851 Rule: generateMetalavaRevertAnnotationsRule,
852 Input: releasedFlaggedApisFile,
853 Output: revertAnnotationsFile,
854 Description: fmt.Sprintf("%s revert annotations", stubsType),
855 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000856
857 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000858}
859
Jihoon Kang3c89f042023-12-19 02:40:22 +0000860func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
861 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700862 if BoolDefault(d.properties.High_mem, false) {
863 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
864 rule.HighMem()
865 }
866
Jihoon Kang3c89f042023-12-19 02:40:22 +0000867 if params.stubConfig.generateStubs {
868 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
869 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700870 }
871
Jihoon Kang3c89f042023-12-19 02:40:22 +0000872 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700873
Jihoon Kang3c89f042023-12-19 02:40:22 +0000874 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000875 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig)
Colin Cross2207f872021-03-24 12:39:08 -0700876 cmd.Implicits(d.Javadoc.implicits)
877
Jihoon Kang3c89f042023-12-19 02:40:22 +0000878 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700879
Jihoon Kang3c89f042023-12-19 02:40:22 +0000880 if params.stubConfig.writeSdkValues {
881 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
882 }
883
884 annotationParams := annotationFlagsParams{
885 migratingNullability: params.stubConfig.migratingNullability,
886 validatingNullability: params.stubConfig.validatingNullability,
887 nullabilityWarningsFile: params.nullabilityWarningsFile,
888 annotationsZip: params.annotationsZip,
889 }
890
Jihoon Kanga11d6792024-03-05 16:12:20 +0000891 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700892 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000893 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700894
Jihoon Kang472f73f2024-03-28 20:59:29 +0000895 if params.stubConfig.doCheckReleased {
896 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
897 }
898
Colin Crossbc139922021-03-25 18:33:16 -0700899 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700900
Colin Cross2207f872021-03-24 12:39:08 -0700901 for _, o := range d.Javadoc.properties.Out {
902 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
903 }
904
Jihoon Kang3c89f042023-12-19 02:40:22 +0000905 return cmd
906}
Colin Cross2207f872021-03-24 12:39:08 -0700907
Jihoon Kang3c89f042023-12-19 02:40:22 +0000908// Sandbox rule for generating the everything stubs and other artifacts
909func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
910 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
911 rule := android.NewRuleBuilder(pctx, ctx)
912 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
913 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
914 SandboxInputs()
915
916 var stubsDir android.OptionalPath
917 if params.generateStubs {
918 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
919 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
920 }
921
922 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000923 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
924 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000925 }
926
Jihoon Kanga11d6792024-03-05 16:12:20 +0000927 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000928 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000929 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000930 }
Jihoon Kangee113282024-01-23 00:16:41 +0000931 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000932 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000933 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000934 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000935 }
936
937 commonCmdParams := stubsCommandParams{
938 srcJarDir: srcJarDir,
939 stubsDir: stubsDir,
940 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000941 metadataDir: d.everythingArtifacts.metadataDir,
942 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
943 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
944 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000945 stubConfig: params,
946 }
947
948 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
949
950 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
951
952 if params.generateStubs {
953 rule.Command().
954 BuiltTool("soong_zip").
955 Flag("-write_if_changed").
956 Flag("-jar").
957 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
958 FlagWithArg("-C ", stubsDir.String()).
959 FlagWithArg("-D ", stubsDir.String())
960 }
961
962 if params.writeSdkValues {
963 rule.Command().
964 BuiltTool("soong_zip").
965 Flag("-write_if_changed").
966 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000967 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
968 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
969 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000970 }
971
972 // TODO: We don't really need two separate API files, but this is a reminiscence of how
973 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
974 if params.doApiLint {
975 rule.Command().Text("touch").Output(d.apiLintTimestamp)
976 }
977 if params.doCheckReleased {
978 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
979 }
980
981 // TODO(b/183630617): rewrapper doesn't support restat rules
982 if !metalavaUseRbe(ctx) {
983 rule.Restat()
984 }
985
986 zipSyncCleanupCmd(rule, srcJarDir)
987
988 rule.Build("metalava", "metalava merged")
989}
990
991// Sandbox rule for generating the everything artifacts that are not run by
992// default but only run based on the module configurations
993func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700994
995 // Add API lint options.
Paul Duffinbaf34782024-05-28 17:27:22 +0100996 treatDocumentationIssuesAsErrors := false
Jihoon Kang3c89f042023-12-19 02:40:22 +0000997 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +0000998 var newSince android.Paths
999 if d.properties.Check_api.Api_lint.New_since != nil {
1000 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
1001 }
Paul Duffin0a71d732024-04-22 13:22:56 +01001002 cmd.Flag("--api-lint")
1003 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001004 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001005 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
1006
Colin Cross0d532412021-03-25 09:38:45 -07001007 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -07001008 if d.Name() != "android.car-system-stubs-docs" &&
1009 d.Name() != "android.car-stubs-docs" {
Paul Duffinbaf34782024-05-28 17:27:22 +01001010 treatDocumentationIssuesAsErrors = true
Colin Cross2207f872021-03-24 12:39:08 -07001011 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
1012 }
1013
1014 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001015 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
1016 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001017
1018 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -07001019 //
1020 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
1021 // message and metalava's one?
1022 msg := `$'` + // Enclose with $' ... '
1023 `************************************************************\n` +
1024 `Your API changes are triggering API Lint warnings or errors.\n` +
1025 `To make these errors go away, fix the code according to the\n` +
1026 `error and/or warning messages above.\n` +
1027 `\n` +
1028 `If it is not possible to do so, there are workarounds:\n` +
1029 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +00001030 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
1031 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -07001032
1033 if baselineFile.Valid() {
1034 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1035 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
1036
1037 msg += fmt.Sprintf(``+
1038 `2. You can update the baseline by executing the following\n`+
1039 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -07001040 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
1041 ` "%s" \\\n`+
1042 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001043 ` To submit the revised baseline.txt to the main Android\n`+
1044 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
1045 } else {
1046 msg += fmt.Sprintf(``+
1047 `2. You can add a baseline file of existing lint failures\n`+
1048 ` to the build rule of %s.\n`, d.Name())
1049 }
1050 // Note the message ends with a ' (single quote), to close the $' ... ' .
1051 msg += `************************************************************\n'`
1052
1053 cmd.FlagWithArg("--error-message:api-lint ", msg)
1054 }
1055
Paul Duffinbaf34782024-05-28 17:27:22 +01001056 if !treatDocumentationIssuesAsErrors {
Paul Duffinb679bdd2024-06-10 14:29:41 +01001057 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffinbaf34782024-05-28 17:27:22 +01001058 }
1059
Colin Cross2207f872021-03-24 12:39:08 -07001060 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001061 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001062 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001063 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001064 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001065 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001066 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1067 }
Colin Cross2207f872021-03-24 12:39:08 -07001068 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1069 msg := `$'\n******************************\n` +
1070 `You have tried to change the API from what has been previously released in\n` +
1071 `an SDK. Please fix the errors listed above.\n` +
1072 `******************************\n'`
1073
1074 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1075 }
1076
Paul Duffin10a23c22023-08-11 22:47:31 +01001077 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1078 // Pass the current API file into metalava so it can use it as the basis for determining how to
1079 // generate the output signature files (both api and removed).
1080 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1081 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1082 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001083}
Paul Duffin10a23c22023-08-11 22:47:31 +01001084
Paul Duffinb679bdd2024-06-10 14:29:41 +01001085// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
1086// hidden as they are very noisy and provide little value.
1087var HIDDEN_DOCUMENTATION_ISSUES = []string{
1088 "Deprecated",
1089 "IntDef",
1090 "Nullable",
1091}
1092
1093func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
1094 // Treat documentation issues as warnings, but error when new.
1095 cmd.Flag("--error-when-new-category").Flag("Documentation")
1096
1097 // Hide some documentation issues that generated a lot of noise for little benefit.
1098 cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
1099}
1100
Jihoon Kang3c89f042023-12-19 02:40:22 +00001101// Sandbox rule for generating exportable stubs and other artifacts
1102func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1103 optionalCmdParams := stubsCommandParams{
1104 stubConfig: params,
1105 }
1106
Jihoon Kang246690a2024-02-01 21:55:01 +00001107 if params.generateStubs {
1108 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1109 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1110 }
1111
Jihoon Kang3c89f042023-12-19 02:40:22 +00001112 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001113 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1114 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1115 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1116 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001117 }
1118
Jihoon Kanga11d6792024-03-05 16:12:20 +00001119 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001120 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001121 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1122 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001123 }
Jihoon Kangee113282024-01-23 00:16:41 +00001124 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1125 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001126 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001127 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001128 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1129 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001130 }
1131
1132 if params.checkApi || String(d.properties.Api_filename) != "" {
1133 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1134 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1135 }
1136
1137 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1138 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1139 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1140 }
1141
1142 d.optionalStubCmd(ctx, optionalCmdParams)
1143}
1144
1145func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1146
1147 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1148 rule := android.NewRuleBuilder(pctx, ctx)
1149 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1150 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1151 SandboxInputs()
1152
1153 if params.stubConfig.generateStubs {
1154 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1155 }
1156
1157 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1158
Jihoon Kang5d701272024-02-15 21:53:49 +00001159 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001160
1161 if params.stubConfig.doApiLint {
1162 // Pass the lint baseline file as an input to resolve the lint errors.
1163 // The exportable stubs generation does not update the lint baseline file.
1164 // Lint baseline file update is handled by the everything stubs
1165 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1166 if baselineFile.Valid() {
1167 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1168 }
1169 }
1170
Paul Duffin71527b72024-05-31 13:30:32 +01001171 // Treat documentation issues as warnings, but error when new.
Paul Duffinb679bdd2024-06-10 14:29:41 +01001172 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffin71527b72024-05-31 13:30:32 +01001173
Jihoon Kang3c89f042023-12-19 02:40:22 +00001174 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001175 rule.Command().
1176 BuiltTool("soong_zip").
1177 Flag("-write_if_changed").
1178 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001179 FlagWithOutput("-o ", params.stubsSrcJar).
1180 FlagWithArg("-C ", params.stubsDir.String()).
1181 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001182 }
1183
Jihoon Kang3c89f042023-12-19 02:40:22 +00001184 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001185 rule.Command().
1186 BuiltTool("soong_zip").
1187 Flag("-write_if_changed").
1188 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001189 FlagWithOutput("-o ", params.metadataZip).
1190 FlagWithArg("-C ", params.metadataDir.String()).
1191 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001192 }
1193
Colin Cross6aa5c402021-03-24 12:28:50 -07001194 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001195 if !metalavaUseRbe(ctx) {
1196 rule.Restat()
1197 }
Colin Cross2207f872021-03-24 12:39:08 -07001198
Jihoon Kang3c89f042023-12-19 02:40:22 +00001199 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001200
Jihoon Kang3c89f042023-12-19 02:40:22 +00001201 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1202}
1203
1204func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1205 deps := d.Javadoc.collectDeps(ctx)
1206
1207 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1208 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1209
1210 // Add options for the other optional tasks: API-lint and check-released.
1211 // We generate separate timestamp files for them.
1212 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1213 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1214
1215 writeSdkValues := Bool(d.properties.Write_sdk_values)
1216
1217 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1218
1219 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1220 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1221 String(d.properties.Validate_nullability_from_list) != "")
1222
1223 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1224 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1225
1226 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001227 javaVersion: javaVersion,
1228 deps: deps,
1229 checkApi: checkApi,
1230 generateStubs: generateStubs,
1231 doApiLint: doApiLint,
1232 doCheckReleased: doCheckReleased,
1233 writeSdkValues: writeSdkValues,
1234 migratingNullability: migratingNullability,
1235 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001236 }
1237 stubCmdParams.stubsType = Everything
1238 // Create default (i.e. "everything" stubs) rule for metalava
1239 d.everythingStubCmd(ctx, stubCmdParams)
1240
Jihoon Kangd40c5912024-03-05 16:12:20 +00001241 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001242 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1243 // strips all flagged apis to generate the "exportable" stubs
1244 stubCmdParams.stubsType = Exportable
1245 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001246
Paul Duffine7a86642022-08-16 15:43:20 +00001247 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1248
1249 if len(d.Javadoc.properties.Out) > 0 {
1250 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1251 }
1252
1253 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1254 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1255 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1256
1257 if baselineFile.Valid() {
1258 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1259 }
1260
Jihoon Kang3c89f042023-12-19 02:40:22 +00001261 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001262
1263 rule := android.NewRuleBuilder(pctx, ctx)
1264
1265 // Diff command line.
1266 // -F matches the closest "opening" line, such as "package android {"
1267 // and " public class Intent {".
1268 diff := `diff -u -F '{ *$'`
1269
1270 rule.Command().Text("( true")
1271 rule.Command().
1272 Text(diff).
1273 Input(apiFile).Input(d.apiFile)
1274
1275 rule.Command().
1276 Text(diff).
1277 Input(removedApiFile).Input(d.removedApiFile)
1278
1279 msg := fmt.Sprintf(`\n******************************\n`+
1280 `You have tried to change the API from what has been previously approved.\n\n`+
1281 `To make these errors go away, you have two choices:\n`+
1282 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1283 ` to the new methods, etc. shown in the above diff.\n\n`+
1284 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1285 ` m %s-update-current-api\n\n`+
1286 ` To submit the revised current.txt to the main Android repository,\n`+
1287 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001288 `If your build failed due to stub validation, you can resolve the errors with\n`+
1289 `either of the two choices above and try re-building the target.\n`+
1290 `If the mismatch between the stubs and the current.txt is intended,\n`+
1291 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001292 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1293 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001294 `******************************\n`, ctx.ModuleName())
1295
1296 rule.Command().
1297 Text("touch").Output(d.checkCurrentApiTimestamp).
1298 Text(") || (").
1299 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1300 Text("; exit 38").
1301 Text(")")
1302
1303 rule.Build("metalavaCurrentApiCheck", "check current API")
1304
Jihoon Kang3c89f042023-12-19 02:40:22 +00001305 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001306
1307 // update API rule
1308 rule = android.NewRuleBuilder(pctx, ctx)
1309
1310 rule.Command().Text("( true")
1311
1312 rule.Command().
1313 Text("cp").Flag("-f").
1314 Input(d.apiFile).Flag(apiFile.String())
1315
1316 rule.Command().
1317 Text("cp").Flag("-f").
1318 Input(d.removedApiFile).Flag(removedApiFile.String())
1319
1320 msg = "failed to update public API"
1321
1322 rule.Command().
1323 Text("touch").Output(d.updateCurrentApiTimestamp).
1324 Text(") || (").
1325 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1326 Text("; exit 38").
1327 Text(")")
1328
1329 rule.Build("metalavaCurrentApiUpdate", "update current API")
1330 }
1331
Colin Cross2207f872021-03-24 12:39:08 -07001332 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001333 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001334 ctx.PropertyErrorf("check_nullability_warnings",
1335 "Cannot specify check_nullability_warnings unless validating nullability")
1336 }
1337
1338 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1339
Jihoon Kang3c89f042023-12-19 02:40:22 +00001340 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001341
1342 msg := fmt.Sprintf(`\n******************************\n`+
1343 `The warnings encountered during nullability annotation validation did\n`+
1344 `not match the checked in file of expected warnings. The diffs are shown\n`+
1345 `above. You have two options:\n`+
1346 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1347 ` 2. Update the file of expected warnings by running:\n`+
1348 ` cp %s %s\n`+
1349 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001350 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001351
1352 rule := android.NewRuleBuilder(pctx, ctx)
1353
1354 rule.Command().
1355 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001356 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001357 Text("&&").
1358 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1359 Text(") || (").
1360 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1361 Text("; exit 38").
1362 Text(")")
1363
1364 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1365 }
1366}
1367
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001368func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1369 api_file := d.properties.Check_api.Current.Api_file
1370 api_surface := d.properties.Api_surface
1371
1372 props := struct {
1373 Name *string
1374 Api_surface *string
1375 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001376 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001377 }{}
1378
1379 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1380 props.Api_surface = api_surface
1381 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001382 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001383
1384 ctx.CreateModule(ApiContributionFactory, &props)
1385}
1386
Spandan Das0b555e32022-11-28 18:48:51 +00001387// TODO (b/262014796): Export the API contributions of CorePlatformApi
1388// A map to populate the api surface of a droidstub from a substring appearing in its name
1389// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1390// use a strict naming convention
1391var (
1392 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001393 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001394 "intracore": android.SdkIntraCore,
1395 "intra.core": android.SdkIntraCore,
1396 "system_server": android.SdkSystemServer,
1397 "system-server": android.SdkSystemServer,
1398 "system": android.SdkSystem,
1399 "module_lib": android.SdkModule,
1400 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001401 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001402 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001403 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001404 }
1405)
1406
Colin Cross2207f872021-03-24 12:39:08 -07001407func StubsDefaultsFactory() android.Module {
1408 module := &DocDefaults{}
1409
1410 module.AddProperties(
1411 &JavadocProperties{},
1412 &DroidstubsProperties{},
1413 )
1414
1415 android.InitDefaultsModule(module)
1416
1417 return module
1418}
1419
1420var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1421
1422type PrebuiltStubsSourcesProperties struct {
1423 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001424
1425 // Name of the source soong module that gets shadowed by this prebuilt
1426 // If unspecified, follows the naming convention that the source module of
1427 // the prebuilt is Name() without "prebuilt_" prefix
1428 Source_module_name *string
1429
1430 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1431 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1432 // (without any prebuilt_ prefix)
1433 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1434}
1435
1436func (j *PrebuiltStubsSources) BaseModuleName() string {
1437 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1438}
1439
1440func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1441 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001442}
1443
1444type PrebuiltStubsSources struct {
1445 android.ModuleBase
1446 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001447 embeddableInModuleAndImport
1448
Colin Cross2207f872021-03-24 12:39:08 -07001449 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001450
1451 properties PrebuiltStubsSourcesProperties
1452
kgui67007242022-01-25 13:50:25 +08001453 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001454}
1455
Jihoon Kangee113282024-01-23 00:16:41 +00001456func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1457 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001458}
1459
1460func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001461 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001462 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 -07001463 return
1464 }
1465
Anton Hansson86758ac2021-11-03 14:44:12 +00001466 src := p.properties.Srcs[0]
1467 if filepath.Ext(src) == ".srcjar" {
1468 // This is a srcjar. We can use it directly.
1469 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1470 } else {
1471 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001472
Anton Hansson86758ac2021-11-03 14:44:12 +00001473 // This is a directory. Glob the contents just in case the directory does not exist.
1474 srcGlob := src + "/**/*"
1475 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001476
Anton Hansson86758ac2021-11-03 14:44:12 +00001477 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1478 // the path components are invalid it won't in this case because no components
1479 // are specified and the module directory must exist in order to get this far.
1480 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001481
Anton Hansson86758ac2021-11-03 14:44:12 +00001482 rule := android.NewRuleBuilder(pctx, ctx)
1483 rule.Command().
1484 BuiltTool("soong_zip").
1485 Flag("-write_if_changed").
1486 Flag("-jar").
1487 FlagWithOutput("-o ", outPath).
1488 FlagWithArg("-C ", srcDir.String()).
1489 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1490 rule.Restat()
1491 rule.Build("zip src", "Create srcjar from prebuilt source")
1492 p.stubsSrcJar = outPath
1493 }
mrziwangaa2a2b62024-07-01 12:09:20 -07001494
1495 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
1496 // prebuilt droidstubs does not output "exportable" stubs.
1497 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1498 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
Colin Cross2207f872021-03-24 12:39:08 -07001499}
1500
1501func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1502 return &p.prebuilt
1503}
1504
1505func (p *PrebuiltStubsSources) Name() string {
1506 return p.prebuilt.Name(p.ModuleBase.Name())
1507}
1508
1509// prebuilt_stubs_sources imports a set of java source files as if they were
1510// generated by droidstubs.
1511//
1512// By default, a prebuilt_stubs_sources has a single variant that expects a
1513// set of `.java` files generated by droidstubs.
1514//
1515// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1516// for host modules.
1517//
1518// Intended only for use by sdk snapshots.
1519func PrebuiltStubsSourcesFactory() android.Module {
1520 module := &PrebuiltStubsSources{}
1521
1522 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001523 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001524
1525 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001526 InitDroiddocModule(module, android.HostAndDeviceSupported)
1527 return module
1528}