blob: 17c39fcaac60b6ad445e5b3333e080b7c2de2a4a [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
Yu Liucbb50c22025-01-15 20:57:49 +000023 "github.com/google/blueprint"
Colin Cross2207f872021-03-24 12:39:08 -070024 "github.com/google/blueprint/proptools"
25
26 "android/soong/android"
27 "android/soong/java/config"
28 "android/soong/remoteexec"
29)
30
Yu Liucbb50c22025-01-15 20:57:49 +000031type DroidStubsInfo struct {
32 CurrentApiTimestamp android.Path
33}
34
35var DroidStubsInfoProvider = blueprint.NewProvider[DroidStubsInfo]()
36
Pedro Loureirocc203502021-10-04 17:24:00 +000037// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070038var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000039
Jihoon Kang6592e872023-12-19 01:13:16 +000040type StubsType int
41
42const (
43 Everything StubsType = iota
44 Runtime
45 Exportable
Jihoon Kang78f89142023-12-27 01:40:29 +000046 Unavailable
Jihoon Kang6592e872023-12-19 01:13:16 +000047)
48
49func (s StubsType) String() string {
50 switch s {
51 case Everything:
52 return "everything"
53 case Runtime:
54 return "runtime"
55 case Exportable:
56 return "exportable"
57 default:
58 return ""
59 }
60}
61
Jihoon Kang5d701272024-02-15 21:53:49 +000062func StringToStubsType(s string) StubsType {
63 switch strings.ToLower(s) {
64 case Everything.String():
65 return Everything
66 case Runtime.String():
67 return Runtime
68 case Exportable.String():
69 return Exportable
70 default:
71 return Unavailable
72 }
73}
74
Colin Cross2207f872021-03-24 12:39:08 -070075func init() {
76 RegisterStubsBuildComponents(android.InitRegistrationContext)
77}
78
79func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
80 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
81
82 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
83 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
84
85 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
86}
87
Jihoon Kangee113282024-01-23 00:16:41 +000088type stubsArtifacts struct {
89 nullabilityWarningsFile android.WritablePath
90 annotationsZip android.WritablePath
91 apiVersionsXml android.WritablePath
92 metadataZip android.WritablePath
93 metadataDir android.WritablePath
94}
95
Colin Cross2207f872021-03-24 12:39:08 -070096// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070097type Droidstubs struct {
98 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000099 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -0700100
Jihoon Kangee113282024-01-23 00:16:41 +0000101 properties DroidstubsProperties
102 apiFile android.Path
103 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -0700104
105 checkCurrentApiTimestamp android.WritablePath
106 updateCurrentApiTimestamp android.WritablePath
107 checkLastReleasedApiTimestamp android.WritablePath
108 apiLintTimestamp android.WritablePath
109 apiLintReport android.WritablePath
110
111 checkNullabilityWarningsTimestamp android.WritablePath
112
Jihoon Kangee113282024-01-23 00:16:41 +0000113 everythingArtifacts stubsArtifacts
114 exportableArtifacts stubsArtifacts
Jihoon Kang3c89f042023-12-19 02:40:22 +0000115
Jihoon Kangee113282024-01-23 00:16:41 +0000116 exportableApiFile android.WritablePath
117 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700118}
119
120type DroidstubsProperties struct {
121 // The generated public API filename by Metalava, defaults to <module>_api.txt
122 Api_filename *string
123
124 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
125 Removed_api_filename *string
126
Colin Cross2207f872021-03-24 12:39:08 -0700127 Check_api struct {
128 Last_released ApiToCheck
129
130 Current ApiToCheck
131
132 Api_lint struct {
133 Enabled *bool
134
135 // If set, performs api_lint on any new APIs not found in the given signature file
136 New_since *string `android:"path"`
137
138 // If not blank, path to the baseline txt file for approved API lint violations.
139 Baseline_file *string `android:"path"`
140 }
141 }
142
143 // user can specify the version of previous released API file in order to do compatibility check.
144 Previous_api *string `android:"path"`
145
146 // is set to true, Metalava will allow framework SDK to contain annotations.
147 Annotations_enabled *bool
148
149 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
150 Merge_annotations_dirs []string
151
152 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
153 Merge_inclusion_annotations_dirs []string
154
155 // a file containing a list of classes to do nullability validation for.
156 Validate_nullability_from_list *string
157
158 // a file containing expected warnings produced by validation of nullability annotations.
159 Check_nullability_warnings *string
160
161 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
162 Create_doc_stubs *bool
163
164 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
165 // Has no effect if create_doc_stubs: true.
166 Output_javadoc_comments *bool
167
168 // if set to false then do not write out stubs. Defaults to true.
169 //
170 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
171 Generate_stubs *bool
172
173 // 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 -0400174 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700175 High_mem *bool
176
satayev783195c2021-06-23 21:49:57 +0100177 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700178 Api_levels_annotations_enabled *bool
179
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000180 // Apply the api levels database created by this module rather than generating one in this droidstubs.
181 Api_levels_module *string
182
Colin Cross2207f872021-03-24 12:39:08 -0700183 // the dirs which Metalava extracts API levels annotations from.
184 Api_levels_annotations_dirs []string
185
Cole Faust051fa912022-10-05 12:45:42 -0700186 // 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 +0100187 Api_levels_sdk_type *string
188
Colin Cross2207f872021-03-24 12:39:08 -0700189 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
190 Api_levels_jar_filename *string
191
192 // if set to true, collect the values used by the Dev tools and
193 // write them in files packaged with the SDK. Defaults to false.
194 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200195
196 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
197 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
198 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000199
200 // API surface of this module. If set, the module contributes to an API surface.
201 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
202 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000203
204 // a list of aconfig_declarations module names that the stubs generated in this module
205 // depend on.
206 Aconfig_declarations []string
Paul Duffin27819362024-07-22 21:03:50 +0100207
208 // List of hard coded filegroups containing Metalava config files that are passed to every
209 // Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
210 ConfigFiles []string `android:"path" blueprint:"mutated"`
Colin Cross2207f872021-03-24 12:39:08 -0700211}
212
Anton Hansson52609322021-05-05 10:36:05 +0100213// Used by xsd_config
214type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000215 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100216}
217
218type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000219 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000220}
221
Anton Hansson52609322021-05-05 10:36:05 +0100222// Provider of information about API stubs, used by java_sdk_library.
223type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000224 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100225 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000226 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100227
228 ApiStubsSrcProvider
229}
230
Jihoon Kang063ec002023-06-28 01:16:23 +0000231type currentApiTimestampProvider interface {
232 CurrentApiTimestamp() android.Path
233}
234
Jihoon Kang3c89f042023-12-19 02:40:22 +0000235type annotationFlagsParams struct {
236 migratingNullability bool
237 validatingNullability bool
238 nullabilityWarningsFile android.WritablePath
239 annotationsZip android.WritablePath
240}
241type stubsCommandParams struct {
242 srcJarDir android.ModuleOutPath
243 stubsDir android.OptionalPath
244 stubsSrcJar android.WritablePath
245 metadataZip android.WritablePath
246 metadataDir android.WritablePath
247 apiVersionsXml android.WritablePath
248 nullabilityWarningsFile android.WritablePath
249 annotationsZip android.WritablePath
250 stubConfig stubsCommandConfigParams
251}
252type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000253 stubsType StubsType
254 javaVersion javaVersion
255 deps deps
256 checkApi bool
257 generateStubs bool
258 doApiLint bool
259 doCheckReleased bool
260 writeSdkValues bool
261 migratingNullability bool
262 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000263}
264
Colin Cross2207f872021-03-24 12:39:08 -0700265// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
266// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
267// a droiddoc module to generate documentation.
268func DroidstubsFactory() android.Module {
269 module := &Droidstubs{}
270
271 module.AddProperties(&module.properties,
272 &module.Javadoc.properties)
Paul Duffin27819362024-07-22 21:03:50 +0100273 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Spandan Das2cc80ba2023-10-27 17:21:52 +0000274 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700275
276 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000277
278 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
279 module.createApiContribution(ctx)
280 })
Colin Cross2207f872021-03-24 12:39:08 -0700281 return module
282}
283
284// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
285// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
286// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
287// module when symbols needed by the source files are provided by java_library_host modules.
288func DroidstubsHostFactory() android.Module {
289 module := &Droidstubs{}
290
291 module.AddProperties(&module.properties,
292 &module.Javadoc.properties)
293
Paul Duffin27819362024-07-22 21:03:50 +0100294 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Colin Cross2207f872021-03-24 12:39:08 -0700295 InitDroiddocModule(module, android.HostSupported)
296 return module
297}
298
Jihoon Kang246690a2024-02-01 21:55:01 +0000299func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000300 switch stubsType {
301 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000302 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000303 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000304 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000305 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000306 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000307 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000308 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000309}
310
Jihoon Kang246690a2024-02-01 21:55:01 +0000311func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000312 switch stubsType {
313 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000314 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000315 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000316 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000317 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000318 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000319 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000320 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000321 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000322 }
323 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000324}
325
Jihoon Kang246690a2024-02-01 21:55:01 +0000326func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000327 switch stubsType {
328 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000329 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000330 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000331 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000332 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000333 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 +0000334 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000335 if ret == nil && err == nil {
336 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
337 }
338 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000339}
340
Jihoon Kang246690a2024-02-01 21:55:01 +0000341func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000342 switch stubsType {
343 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000344 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000345 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000346 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000347 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000348 if ret == nil && err == nil {
349 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
350 }
351 return ret, err
352}
353
354func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
355 switch stubsType {
356 case Everything:
357 ret, err = d.removedApiFile, nil
358 case Exportable:
359 ret, err = d.exportableRemovedApiFile, nil
360 default:
361 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
362 }
363 if ret == nil && err == nil {
364 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
365 }
366 return ret, err
367}
368
369func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
370 switch stubsType {
371 case Everything:
372 ret, err = d.stubsSrcJar, nil
373 case Exportable:
374 ret, err = d.exportableStubsSrcJar, nil
375 default:
376 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
377 }
378 if ret == nil && err == nil {
379 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
380 }
381 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000382}
383
Jihoon Kang063ec002023-06-28 01:16:23 +0000384func (d *Droidstubs) CurrentApiTimestamp() android.Path {
385 return d.checkCurrentApiTimestamp
386}
387
Colin Cross2207f872021-03-24 12:39:08 -0700388var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
389var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
390var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000391var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000392var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700393
394func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
395 d.Javadoc.addDeps(ctx)
396
397 if len(d.properties.Merge_annotations_dirs) != 0 {
398 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
399 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
400 }
401 }
402
403 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
404 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
405 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
406 }
407 }
408
409 if len(d.properties.Api_levels_annotations_dirs) != 0 {
410 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
411 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
412 }
413 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000414
Jihoon Kang6592e872023-12-19 01:13:16 +0000415 if len(d.properties.Aconfig_declarations) != 0 {
416 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
417 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
418 }
419 }
420
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000421 if d.properties.Api_levels_module != nil {
422 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
423 }
Colin Cross2207f872021-03-24 12:39:08 -0700424}
425
Jihoon Kang3c89f042023-12-19 02:40:22 +0000426func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
427 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
428}
429
430func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000431
Jihoon Kang36c3d962024-03-14 17:28:44 +0000432 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
433 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
434 cmd.FlagWithOutput("--api ", uncheckedApiFile)
435 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000436 if stubsType == Everything {
437 d.apiFile = uncheckedApiFile
438 } else if stubsType == Exportable {
439 d.exportableApiFile = uncheckedApiFile
440 }
Colin Cross2207f872021-03-24 12:39:08 -0700441 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000442 if stubsType == Everything {
443 // If check api is disabled then make the source file available for export.
444 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
445 } else if stubsType == Exportable {
446 d.exportableApiFile = uncheckedApiFile
447 }
Colin Cross2207f872021-03-24 12:39:08 -0700448 }
449
Jihoon Kang36c3d962024-03-14 17:28:44 +0000450 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
451 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
452 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000453 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000454 if stubsType == Everything {
455 d.removedApiFile = uncheckedRemovedFile
456 } else if stubsType == Exportable {
457 d.exportableRemovedApiFile = uncheckedRemovedFile
458 }
Colin Cross2207f872021-03-24 12:39:08 -0700459 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000460 if stubsType == Everything {
461 // If check api is disabled then make the source removed api file available for export.
462 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
463 } else if stubsType == Exportable {
464 d.exportableRemovedApiFile = uncheckedRemovedFile
465 }
Colin Cross2207f872021-03-24 12:39:08 -0700466 }
467
Colin Cross2207f872021-03-24 12:39:08 -0700468 if stubsDir.Valid() {
469 if Bool(d.properties.Create_doc_stubs) {
470 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
471 } else {
472 cmd.FlagWithArg("--stubs ", stubsDir.String())
473 if !Bool(d.properties.Output_javadoc_comments) {
474 cmd.Flag("--exclude-documentation-from-stubs")
475 }
476 }
477 }
478}
479
Jihoon Kang3c89f042023-12-19 02:40:22 +0000480func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000481 if Bool(d.properties.Annotations_enabled) {
482 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100483
Jihoon Kanga11d6792024-03-05 16:12:20 +0000484 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000485 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
486 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000487 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000488
Jihoon Kanga11d6792024-03-05 16:12:20 +0000489 if s := String(d.properties.Validate_nullability_from_list); s != "" {
490 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
491 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000492
Jihoon Kanga11d6792024-03-05 16:12:20 +0000493 if params.validatingNullability {
494 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
495 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000496
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000497 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000498
Jihoon Kanga11d6792024-03-05 16:12:20 +0000499 if len(d.properties.Merge_annotations_dirs) != 0 {
500 d.mergeAnnoDirFlags(ctx, cmd)
501 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000502
Jihoon Kanga11d6792024-03-05 16:12:20 +0000503 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700504 }
Colin Cross2207f872021-03-24 12:39:08 -0700505}
506
507func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
508 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
509 if t, ok := m.(*ExportedDroiddocDir); ok {
510 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
511 } else {
512 ctx.PropertyErrorf("merge_annotations_dirs",
513 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
514 }
515 })
516}
517
518func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
519 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
520 if t, ok := m.(*ExportedDroiddocDir); ok {
521 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
522 } else {
523 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
524 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
525 }
526 })
527}
528
Jihoon Kanga11d6792024-03-05 16:12:20 +0000529func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000530 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000531 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000532 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000533 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000534 } else {
535 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
536 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000537 if stubsType == Everything {
538 apiVersions = s.everythingArtifacts.apiVersionsXml
539 } else if stubsType == Exportable {
540 apiVersions = s.exportableArtifacts.apiVersionsXml
541 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000542 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000543 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000544 } else {
545 ctx.PropertyErrorf("api_levels_module",
546 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
547 }
548 })
Colin Cross2207f872021-03-24 12:39:08 -0700549 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000550 if apiVersions != nil {
551 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
552 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
553 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
554 }
555}
Colin Cross2207f872021-03-24 12:39:08 -0700556
Paul Duffin5a195f42024-05-01 12:52:35 +0100557// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
558// `system-server` directories that contain all the APIs provided by the platform and updatable
559// modules because the `android.jar` files do not. See b/337836752.
560const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
561
Jihoon Kang3c89f042023-12-19 02:40:22 +0000562func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700563 if len(d.properties.Api_levels_annotations_dirs) == 0 {
564 ctx.PropertyErrorf("api_levels_annotations_dirs",
565 "has to be non-empty if api levels annotations was enabled!")
566 }
567
Jihoon Kang3c89f042023-12-19 02:40:22 +0000568 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700569
570 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
571
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100572 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
573 // Add all relevant --android-jar-pattern patterns for Metalava.
574 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
575 // an actual file present on disk (in the order the patterns were passed). For system APIs for
576 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
577 // for older releases. Similarly, module-lib falls back to system API.
578 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100579 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
580 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100581 case "system-server":
582 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
583 case "module-lib":
584 sdkDirs = []string{"module-lib", "system", "public"}
585 case "system":
586 sdkDirs = []string{"system", "public"}
587 case "public":
588 sdkDirs = []string{"public"}
589 default:
590 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
591 return
592 }
593
Paul Duffin92efc612024-05-02 17:18:05 +0100594 // Construct a pattern to match the appropriate extensions that should be included in the
595 // generated api-versions.xml file.
596 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100597 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
598 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100599 // The exception is for system-server which needs to include module-lib and system-server. That
600 // is because while system-server extends module-lib the system-server extension directory only
601 // contains service-* modules which provide system-server APIs it does not list the modules which
602 // only provide a module-lib, so they have to be included separately.
603 extensionSurfacesPattern := sdkDirs[0]
604 if apiLevelsSdkType == "system-server" {
605 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
606 // a pattern that will match either.
607 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
608 }
609 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100610
satayev783195c2021-06-23 21:49:57 +0100611 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200612 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700613 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
614 if t, ok := m.(*ExportedDroiddocDir); ok {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100615 extRegex := regexp.MustCompile(t.dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200616
617 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
618 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700619 for _, dep := range t.deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100620 // Check to see if it matches an extension first.
621 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200622 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
623 if extensions_dir == "" {
624 extensions_dir = t.dir.String() + "/extensions"
625 }
626 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100627 } else if depBase == filename {
628 // 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 -0700629 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100630 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
631 // The output api-versions.xml has been requested to include information on SDK
632 // extensions. That means it also needs to include
633 // so
634 // The module-lib and system-server directories should use `android-plus-updatable.jar`
635 // instead of `android.jar`. See AndroidPlusUpdatableJar for more information.
636 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100637 } else if filename != "android.jar" && depBase == "android.jar" {
Colin Cross5f6ffc72021-03-29 21:54:45 -0700638 // Metalava implicitly searches these patterns:
Paul Duffin4c9d3052025-01-07 16:03:10 +0000639 // prebuilts/tools/common/api-versions/android-{version:level}/android.jar
640 // prebuilts/sdk/{version:level}/public/android.jar
Colin Cross5f6ffc72021-03-29 21:54:45 -0700641 // Add android.jar files from the api_levels_annotations_dirs directories to try
642 // to satisfy these patterns. If Metalava can't find a match for an API level
643 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700644 cmd.Implicit(dep)
645 }
646 }
satayev783195c2021-06-23 21:49:57 +0100647
648 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700649 } else {
650 ctx.PropertyErrorf("api_levels_annotations_dirs",
651 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
652 }
653 })
satayev783195c2021-06-23 21:49:57 +0100654
Paul Duffin5a195f42024-05-01 12:52:35 +0100655 // Generate the list of --android-jar-pattern options. The order matters so the first one which
Paul Duffin4c9d3052025-01-07 16:03:10 +0000656 // matches will be the one that is used for a specific api level.
Pedro Loureirocc203502021-10-04 17:24:00 +0000657 for _, sdkDir := range sdkDirs {
658 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100659 addPattern := func(jarFilename string) {
Paul Duffin4c9d3052025-01-07 16:03:10 +0000660 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:level}/%s/%s", dir, sdkDir, jarFilename))
Paul Duffin5a195f42024-05-01 12:52:35 +0100661 }
662
663 if sdkDir == "module-lib" || sdkDir == "system-server" {
664 // The module-lib and system-server android.jars do not include the updatable modules (as
665 // doing so in the source would introduce dependency cycles and the prebuilts have to
666 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
667 // that does include the updatable modules and this pattern will match that. This pattern
668 // is added in addition to the following pattern to decouple this change from the change
669 // to add the `android-plus-updatable.jar`.
670 addPattern(AndroidPlusUpdatableJar)
671 }
672
673 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000674 }
satayev783195c2021-06-23 21:49:57 +0100675 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200676
677 if d.properties.Extensions_info_file != nil {
678 if extensions_dir == "" {
679 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
680 }
681 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
682 cmd.Implicit(info_file)
683 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
684 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
685 }
Colin Cross2207f872021-03-24 12:39:08 -0700686}
687
Jihoon Kang472f73f2024-03-28 20:59:29 +0000688func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
689 if len(d.Javadoc.properties.Out) > 0 {
690 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
691 }
692
Jihoon Kang5623e542024-01-31 23:27:26 +0000693 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
694 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000695
Jihoon Kang5623e542024-01-31 23:27:26 +0000696 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
697 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000698
699 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
700 if baselineFile.Valid() {
701 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
702 }
703}
704
Colin Crosse52c2ac2022-03-28 17:03:35 -0700705func metalavaUseRbe(ctx android.ModuleContext) bool {
706 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
707}
708
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000709func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
Paul Duffin27819362024-07-22 21:03:50 +0100710 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams, configFiles android.Paths) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700711 rule.Command().Text("rm -rf").Flag(homeDir.String())
712 rule.Command().Text("mkdir -p").Flag(homeDir.String())
713
Anton Hansson556e8142021-06-04 16:20:25 +0100714 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700715 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
716
Colin Crosse52c2ac2022-03-28 17:03:35 -0700717 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700718 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700719 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000720 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
721 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700722 labels := map[string]string{"type": "tool", "name": "metalava"}
723 // TODO: metalava pool rejects these jobs
724 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
725 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000726 Labels: labels,
727 ExecStrategy: execStrategy,
728 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
729 Platform: map[string]string{remoteexec.PoolKey: pool},
730 Compare: compare,
731 NumLocalRuns: 1,
732 NumRemoteRuns: 1,
733 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700734 })
Colin Cross2207f872021-03-24 12:39:08 -0700735 }
736
Colin Cross6aa5c402021-03-24 12:28:50 -0700737 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700738 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400739 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000740 FlagWithArg("--java-source ", params.javaVersion.String()).
741 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700742 FlagWithInput("@", srcJarList)
743
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100744 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
745 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000746 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
747 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100748 if len(combinedPaths) > 0 {
749 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700750 }
751
Liz Kammere09e20e2023-10-16 15:07:54 -0400752 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000753
Paul Duffin27819362024-07-22 21:03:50 +0100754 addMetalavaConfigFilesToCmd(cmd, configFiles)
755
Colin Cross2207f872021-03-24 12:39:08 -0700756 return cmd
757}
758
Paul Duffin27819362024-07-22 21:03:50 +0100759// MetalavaConfigFilegroup is the name of the filegroup in build/soong/java/metalava that lists
760// the configuration files to pass to Metalava.
761const MetalavaConfigFilegroup = "metalava-config-files"
762
763// Get a reference to the MetalavaConfigFilegroup suitable for use in a property.
764func getMetalavaConfigFilegroupReference() []string {
765 return []string{":" + MetalavaConfigFilegroup}
766}
767
768// addMetalavaConfigFilesToCmd adds --config-file options to use the config files list in the
769// MetalavaConfigFilegroup filegroup.
770func addMetalavaConfigFilesToCmd(cmd *android.RuleBuilderCommand, configFiles android.Paths) {
771 cmd.FlagForEachInput("--config-file ", configFiles)
772}
773
Jihoon Kang3c89f042023-12-19 02:40:22 +0000774// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
775// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
776// property is defined, apply transformations and only revert the flagged apis that are not
777// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000778func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang6592e872023-12-19 01:13:16 +0000779 var filterArgs string
780 switch stubsType {
781 // No flagged apis specific flags need to be passed to metalava when generating
782 // everything stubs
783 case Everything:
784 return
785
786 case Runtime:
787 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
788
789 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000790 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
791 // the flagged apis that have read_write permissions are exposed on top of the enabled
792 // and read_only apis. This is to support local override of flag values at runtime.
793 if ctx.Config().ReleaseExportRuntimeApis() {
794 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
795 } else {
796 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
797 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000798 }
799
Jihoon Kangf1e0ff02024-11-20 21:10:40 +0000800 if len(aconfigFlagsPaths) == 0 {
801 // This argument should not be added for "everything" stubs
802 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
803 return
804 }
805
806 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
807 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
808
Jihoon Kang6592e872023-12-19 01:13:16 +0000809 ctx.Build(pctx, android.BuildParams{
810 Rule: gatherReleasedFlaggedApisRule,
811 Inputs: aconfigFlagsPaths,
812 Output: releasedFlaggedApisFile,
813 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
814 Args: map[string]string{
815 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
816 "filter_args": filterArgs,
817 },
818 })
819
820 ctx.Build(pctx, android.BuildParams{
821 Rule: generateMetalavaRevertAnnotationsRule,
822 Input: releasedFlaggedApisFile,
823 Output: revertAnnotationsFile,
824 Description: fmt.Sprintf("%s revert annotations", stubsType),
825 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000826
827 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000828}
829
Jihoon Kang3c89f042023-12-19 02:40:22 +0000830func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
831 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700832 if BoolDefault(d.properties.High_mem, false) {
833 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
834 rule.HighMem()
835 }
836
Jihoon Kang3c89f042023-12-19 02:40:22 +0000837 if params.stubConfig.generateStubs {
838 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
839 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700840 }
841
Jihoon Kang3c89f042023-12-19 02:40:22 +0000842 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700843
Jihoon Kang3c89f042023-12-19 02:40:22 +0000844 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
Paul Duffin27819362024-07-22 21:03:50 +0100845
846 configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles)
847
848 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig, configFiles)
Colin Cross2207f872021-03-24 12:39:08 -0700849 cmd.Implicits(d.Javadoc.implicits)
850
Jihoon Kang3c89f042023-12-19 02:40:22 +0000851 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700852
Jihoon Kang3c89f042023-12-19 02:40:22 +0000853 if params.stubConfig.writeSdkValues {
854 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
855 }
856
857 annotationParams := annotationFlagsParams{
858 migratingNullability: params.stubConfig.migratingNullability,
859 validatingNullability: params.stubConfig.validatingNullability,
860 nullabilityWarningsFile: params.nullabilityWarningsFile,
861 annotationsZip: params.annotationsZip,
862 }
863
Jihoon Kanga11d6792024-03-05 16:12:20 +0000864 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700865 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000866 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700867
Jihoon Kang472f73f2024-03-28 20:59:29 +0000868 if params.stubConfig.doCheckReleased {
869 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
870 }
871
Colin Crossbc139922021-03-25 18:33:16 -0700872 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700873
Colin Cross2207f872021-03-24 12:39:08 -0700874 for _, o := range d.Javadoc.properties.Out {
875 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
876 }
877
Jihoon Kang3c89f042023-12-19 02:40:22 +0000878 return cmd
879}
Colin Cross2207f872021-03-24 12:39:08 -0700880
Jihoon Kang3c89f042023-12-19 02:40:22 +0000881// Sandbox rule for generating the everything stubs and other artifacts
882func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
883 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
884 rule := android.NewRuleBuilder(pctx, ctx)
885 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
886 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
887 SandboxInputs()
888
889 var stubsDir android.OptionalPath
890 if params.generateStubs {
891 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
892 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
893 }
894
895 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000896 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
897 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000898 }
899
Jihoon Kanga11d6792024-03-05 16:12:20 +0000900 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000901 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000902 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000903 }
Jihoon Kangee113282024-01-23 00:16:41 +0000904 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000905 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000906 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000907 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000908 }
909
910 commonCmdParams := stubsCommandParams{
911 srcJarDir: srcJarDir,
912 stubsDir: stubsDir,
913 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000914 metadataDir: d.everythingArtifacts.metadataDir,
915 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
916 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
917 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000918 stubConfig: params,
919 }
920
921 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
922
923 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
924
925 if params.generateStubs {
926 rule.Command().
927 BuiltTool("soong_zip").
928 Flag("-write_if_changed").
929 Flag("-jar").
930 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
931 FlagWithArg("-C ", stubsDir.String()).
932 FlagWithArg("-D ", stubsDir.String())
933 }
934
935 if params.writeSdkValues {
936 rule.Command().
937 BuiltTool("soong_zip").
938 Flag("-write_if_changed").
939 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000940 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
941 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
942 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000943 }
944
945 // TODO: We don't really need two separate API files, but this is a reminiscence of how
946 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
947 if params.doApiLint {
948 rule.Command().Text("touch").Output(d.apiLintTimestamp)
949 }
950 if params.doCheckReleased {
951 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
952 }
953
954 // TODO(b/183630617): rewrapper doesn't support restat rules
955 if !metalavaUseRbe(ctx) {
956 rule.Restat()
957 }
958
959 zipSyncCleanupCmd(rule, srcJarDir)
960
961 rule.Build("metalava", "metalava merged")
962}
963
964// Sandbox rule for generating the everything artifacts that are not run by
965// default but only run based on the module configurations
966func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700967
968 // Add API lint options.
Paul Duffinbaf34782024-05-28 17:27:22 +0100969 treatDocumentationIssuesAsErrors := false
Jihoon Kang3c89f042023-12-19 02:40:22 +0000970 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +0000971 var newSince android.Paths
972 if d.properties.Check_api.Api_lint.New_since != nil {
973 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
974 }
Paul Duffin0a71d732024-04-22 13:22:56 +0100975 cmd.Flag("--api-lint")
976 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000977 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700978 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
979
Paul Duffinc540bee2024-08-29 15:35:58 +0100980 // If UnflaggedApi issues have not already been configured then make sure that existing
981 // UnflaggedApi issues are reported as warnings but issues in new/changed code are treated as
982 // errors by the Build Warnings Aye Aye Analyzer in Gerrit.
Paul Duffin88d3b392024-08-28 17:37:36 +0100983 // Once existing issues have been fixed this will be changed to error.
Paul Duffinc540bee2024-08-29 15:35:58 +0100984 // TODO(b/362771529): Switch to --error
985 if !strings.Contains(cmd.String(), " UnflaggedApi ") {
986 cmd.Flag("--error-when-new UnflaggedApi")
987 }
Paul Duffin88d3b392024-08-28 17:37:36 +0100988
Colin Cross0d532412021-03-25 09:38:45 -0700989 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700990 if d.Name() != "android.car-system-stubs-docs" &&
991 d.Name() != "android.car-stubs-docs" {
Paul Duffinbaf34782024-05-28 17:27:22 +0100992 treatDocumentationIssuesAsErrors = true
Colin Cross2207f872021-03-24 12:39:08 -0700993 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
994 }
995
996 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000997 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
998 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700999
1000 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -07001001 //
1002 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
1003 // message and metalava's one?
1004 msg := `$'` + // Enclose with $' ... '
1005 `************************************************************\n` +
1006 `Your API changes are triggering API Lint warnings or errors.\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001007 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001008 `To make the failures go away:\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001009 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001010 `1. REQUIRED: Read the messages carefully and address them by` +
1011 ` fixing the API if appropriate.\n` +
1012 `2. If the failure is a false positive, you can suppress it with:\n` +
1013 ` @SuppressLint("<id>")\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +00001014 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -07001015
1016 if baselineFile.Valid() {
1017 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1018 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
1019
1020 msg += fmt.Sprintf(``+
Cole Faust5146e782024-11-15 14:47:49 -08001021 `3. FOR LSC ONLY: You can update the baseline by executing\n`+
Adrian Roos40be6472024-11-05 14:25:35 +00001022 ` the following command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -07001023 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
1024 ` "%s" \\\n`+
1025 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001026 ` To submit the revised baseline.txt to the main Android\n`+
1027 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
1028 } else {
1029 msg += fmt.Sprintf(``+
Adrian Roos40be6472024-11-05 14:25:35 +00001030 `3. FOR LSC ONLY: You can add a baseline file of existing lint failures\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001031 ` to the build rule of %s.\n`, d.Name())
1032 }
1033 // Note the message ends with a ' (single quote), to close the $' ... ' .
1034 msg += `************************************************************\n'`
1035
1036 cmd.FlagWithArg("--error-message:api-lint ", msg)
1037 }
1038
Paul Duffinbaf34782024-05-28 17:27:22 +01001039 if !treatDocumentationIssuesAsErrors {
Paul Duffinb679bdd2024-06-10 14:29:41 +01001040 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffinbaf34782024-05-28 17:27:22 +01001041 }
1042
Colin Cross2207f872021-03-24 12:39:08 -07001043 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001044 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001045 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001046 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001047 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001048 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001049 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1050 }
Colin Cross2207f872021-03-24 12:39:08 -07001051 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1052 msg := `$'\n******************************\n` +
1053 `You have tried to change the API from what has been previously released in\n` +
1054 `an SDK. Please fix the errors listed above.\n` +
1055 `******************************\n'`
1056
1057 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1058 }
1059
Paul Duffin10a23c22023-08-11 22:47:31 +01001060 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1061 // Pass the current API file into metalava so it can use it as the basis for determining how to
1062 // generate the output signature files (both api and removed).
1063 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1064 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1065 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001066}
Paul Duffin10a23c22023-08-11 22:47:31 +01001067
Paul Duffinb679bdd2024-06-10 14:29:41 +01001068// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
1069// hidden as they are very noisy and provide little value.
1070var HIDDEN_DOCUMENTATION_ISSUES = []string{
1071 "Deprecated",
1072 "IntDef",
1073 "Nullable",
1074}
1075
1076func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
1077 // Treat documentation issues as warnings, but error when new.
1078 cmd.Flag("--error-when-new-category").Flag("Documentation")
1079
1080 // Hide some documentation issues that generated a lot of noise for little benefit.
1081 cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
1082}
1083
Jihoon Kang3c89f042023-12-19 02:40:22 +00001084// Sandbox rule for generating exportable stubs and other artifacts
1085func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1086 optionalCmdParams := stubsCommandParams{
1087 stubConfig: params,
1088 }
1089
Jihoon Kang246690a2024-02-01 21:55:01 +00001090 if params.generateStubs {
1091 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1092 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1093 }
1094
Jihoon Kang3c89f042023-12-19 02:40:22 +00001095 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001096 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1097 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1098 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1099 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001100 }
1101
Jihoon Kanga11d6792024-03-05 16:12:20 +00001102 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001103 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001104 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1105 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001106 }
Jihoon Kangee113282024-01-23 00:16:41 +00001107 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1108 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001109 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001110 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001111 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1112 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001113 }
1114
1115 if params.checkApi || String(d.properties.Api_filename) != "" {
1116 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1117 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1118 }
1119
1120 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1121 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1122 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1123 }
1124
1125 d.optionalStubCmd(ctx, optionalCmdParams)
1126}
1127
1128func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1129
1130 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1131 rule := android.NewRuleBuilder(pctx, ctx)
1132 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1133 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1134 SandboxInputs()
1135
1136 if params.stubConfig.generateStubs {
1137 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1138 }
1139
1140 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1141
Jihoon Kang5d701272024-02-15 21:53:49 +00001142 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001143
1144 if params.stubConfig.doApiLint {
1145 // Pass the lint baseline file as an input to resolve the lint errors.
1146 // The exportable stubs generation does not update the lint baseline file.
1147 // Lint baseline file update is handled by the everything stubs
1148 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1149 if baselineFile.Valid() {
1150 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1151 }
1152 }
1153
Paul Duffin71527b72024-05-31 13:30:32 +01001154 // Treat documentation issues as warnings, but error when new.
Paul Duffinb679bdd2024-06-10 14:29:41 +01001155 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffin71527b72024-05-31 13:30:32 +01001156
Jihoon Kang3c89f042023-12-19 02:40:22 +00001157 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001158 rule.Command().
1159 BuiltTool("soong_zip").
1160 Flag("-write_if_changed").
1161 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001162 FlagWithOutput("-o ", params.stubsSrcJar).
1163 FlagWithArg("-C ", params.stubsDir.String()).
1164 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001165 }
1166
Jihoon Kang3c89f042023-12-19 02:40:22 +00001167 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001168 rule.Command().
1169 BuiltTool("soong_zip").
1170 Flag("-write_if_changed").
1171 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001172 FlagWithOutput("-o ", params.metadataZip).
1173 FlagWithArg("-C ", params.metadataDir.String()).
1174 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001175 }
1176
Colin Cross6aa5c402021-03-24 12:28:50 -07001177 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001178 if !metalavaUseRbe(ctx) {
1179 rule.Restat()
1180 }
Colin Cross2207f872021-03-24 12:39:08 -07001181
Jihoon Kang3c89f042023-12-19 02:40:22 +00001182 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001183
Jihoon Kang3c89f042023-12-19 02:40:22 +00001184 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1185}
1186
1187func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1188 deps := d.Javadoc.collectDeps(ctx)
1189
1190 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1191 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1192
1193 // Add options for the other optional tasks: API-lint and check-released.
1194 // We generate separate timestamp files for them.
1195 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1196 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1197
1198 writeSdkValues := Bool(d.properties.Write_sdk_values)
1199
1200 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1201
1202 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1203 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1204 String(d.properties.Validate_nullability_from_list) != "")
1205
1206 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1207 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1208
1209 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001210 javaVersion: javaVersion,
1211 deps: deps,
1212 checkApi: checkApi,
1213 generateStubs: generateStubs,
1214 doApiLint: doApiLint,
1215 doCheckReleased: doCheckReleased,
1216 writeSdkValues: writeSdkValues,
1217 migratingNullability: migratingNullability,
1218 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001219 }
1220 stubCmdParams.stubsType = Everything
1221 // Create default (i.e. "everything" stubs) rule for metalava
1222 d.everythingStubCmd(ctx, stubCmdParams)
1223
Jihoon Kangd40c5912024-03-05 16:12:20 +00001224 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001225 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1226 // strips all flagged apis to generate the "exportable" stubs
1227 stubCmdParams.stubsType = Exportable
1228 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001229
Paul Duffine7a86642022-08-16 15:43:20 +00001230 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1231
1232 if len(d.Javadoc.properties.Out) > 0 {
1233 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1234 }
1235
1236 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1237 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1238 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1239
1240 if baselineFile.Valid() {
1241 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1242 }
1243
Jihoon Kang3c89f042023-12-19 02:40:22 +00001244 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001245
1246 rule := android.NewRuleBuilder(pctx, ctx)
1247
1248 // Diff command line.
1249 // -F matches the closest "opening" line, such as "package android {"
1250 // and " public class Intent {".
1251 diff := `diff -u -F '{ *$'`
1252
1253 rule.Command().Text("( true")
1254 rule.Command().
1255 Text(diff).
1256 Input(apiFile).Input(d.apiFile)
1257
1258 rule.Command().
1259 Text(diff).
1260 Input(removedApiFile).Input(d.removedApiFile)
1261
1262 msg := fmt.Sprintf(`\n******************************\n`+
1263 `You have tried to change the API from what has been previously approved.\n\n`+
1264 `To make these errors go away, you have two choices:\n`+
1265 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1266 ` to the new methods, etc. shown in the above diff.\n\n`+
1267 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1268 ` m %s-update-current-api\n\n`+
1269 ` To submit the revised current.txt to the main Android repository,\n`+
1270 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001271 `If your build failed due to stub validation, you can resolve the errors with\n`+
1272 `either of the two choices above and try re-building the target.\n`+
1273 `If the mismatch between the stubs and the current.txt is intended,\n`+
1274 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001275 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1276 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001277 `******************************\n`, ctx.ModuleName())
1278
1279 rule.Command().
1280 Text("touch").Output(d.checkCurrentApiTimestamp).
1281 Text(") || (").
1282 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1283 Text("; exit 38").
1284 Text(")")
1285
1286 rule.Build("metalavaCurrentApiCheck", "check current API")
1287
Jihoon Kang3c89f042023-12-19 02:40:22 +00001288 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001289
1290 // update API rule
1291 rule = android.NewRuleBuilder(pctx, ctx)
1292
1293 rule.Command().Text("( true")
1294
1295 rule.Command().
1296 Text("cp").Flag("-f").
1297 Input(d.apiFile).Flag(apiFile.String())
1298
1299 rule.Command().
1300 Text("cp").Flag("-f").
1301 Input(d.removedApiFile).Flag(removedApiFile.String())
1302
1303 msg = "failed to update public API"
1304
1305 rule.Command().
1306 Text("touch").Output(d.updateCurrentApiTimestamp).
1307 Text(") || (").
1308 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1309 Text("; exit 38").
1310 Text(")")
1311
1312 rule.Build("metalavaCurrentApiUpdate", "update current API")
1313 }
1314
Colin Cross2207f872021-03-24 12:39:08 -07001315 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001316 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001317 ctx.PropertyErrorf("check_nullability_warnings",
1318 "Cannot specify check_nullability_warnings unless validating nullability")
1319 }
1320
1321 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1322
Jihoon Kang3c89f042023-12-19 02:40:22 +00001323 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001324
1325 msg := fmt.Sprintf(`\n******************************\n`+
1326 `The warnings encountered during nullability annotation validation did\n`+
1327 `not match the checked in file of expected warnings. The diffs are shown\n`+
1328 `above. You have two options:\n`+
1329 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1330 ` 2. Update the file of expected warnings by running:\n`+
1331 ` cp %s %s\n`+
1332 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001333 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001334
1335 rule := android.NewRuleBuilder(pctx, ctx)
1336
1337 rule.Command().
1338 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001339 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001340 Text("&&").
1341 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1342 Text(") || (").
1343 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1344 Text("; exit 38").
1345 Text(")")
1346
1347 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1348 }
mrziwang39e68ff2024-07-01 16:35:32 -07001349
Yu Liucbb50c22025-01-15 20:57:49 +00001350 android.SetProvider(ctx, DroidStubsInfoProvider, DroidStubsInfo{
1351 CurrentApiTimestamp: d.CurrentApiTimestamp(),
1352 })
1353
mrziwang39e68ff2024-07-01 16:35:32 -07001354 d.setOutputFiles(ctx)
1355}
1356
1357// This method sets the outputFiles property, which is used to set the
1358// OutputFilesProvider later.
1359// Droidstubs' tag supports specifying with the stubs type.
1360// While supporting the pre-existing tags, it also supports tags with
1361// the stubs type prefix. Some examples are shown below:
1362// {.annotations.zip} - pre-existing behavior. Returns the path to the
1363// annotation zip.
1364// {.exportable} - Returns the path to the exportable stubs src jar.
1365// {.exportable.annotations.zip} - Returns the path to the exportable
1366// annotations zip file.
1367// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
1368// xml file. For unsupported combinations, the default everything output file
1369// is returned.
1370func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) {
1371 tagToOutputFileFunc := map[string]func(StubsType) (android.Path, error){
1372 "": d.StubsSrcJar,
1373 ".docs.zip": d.DocZip,
1374 ".api.txt": d.ApiFilePath,
1375 android.DefaultDistTag: d.ApiFilePath,
1376 ".removed-api.txt": d.RemovedApiFilePath,
1377 ".annotations.zip": d.AnnotationsZip,
1378 ".api_versions.xml": d.ApiVersionsXmlFilePath,
1379 }
1380 stubsTypeToPrefix := map[StubsType]string{
1381 Everything: "",
1382 Exportable: ".exportable",
1383 }
1384 for _, tag := range android.SortedKeys(tagToOutputFileFunc) {
1385 for _, stubType := range android.SortedKeys(stubsTypeToPrefix) {
1386 tagWithPrefix := stubsTypeToPrefix[stubType] + tag
1387 outputFile, err := tagToOutputFileFunc[tag](stubType)
Cole Faust5146e782024-11-15 14:47:49 -08001388 if err == nil && outputFile != nil {
mrziwang39e68ff2024-07-01 16:35:32 -07001389 ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix)
1390 }
1391 }
1392 }
Colin Cross2207f872021-03-24 12:39:08 -07001393}
1394
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001395func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1396 api_file := d.properties.Check_api.Current.Api_file
1397 api_surface := d.properties.Api_surface
1398
1399 props := struct {
1400 Name *string
1401 Api_surface *string
1402 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001403 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001404 }{}
1405
1406 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1407 props.Api_surface = api_surface
1408 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001409 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001410
1411 ctx.CreateModule(ApiContributionFactory, &props)
1412}
1413
Spandan Das0b555e32022-11-28 18:48:51 +00001414// TODO (b/262014796): Export the API contributions of CorePlatformApi
1415// A map to populate the api surface of a droidstub from a substring appearing in its name
1416// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1417// use a strict naming convention
1418var (
1419 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001420 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001421 "intracore": android.SdkIntraCore,
1422 "intra.core": android.SdkIntraCore,
1423 "system_server": android.SdkSystemServer,
1424 "system-server": android.SdkSystemServer,
1425 "system": android.SdkSystem,
1426 "module_lib": android.SdkModule,
1427 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001428 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001429 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001430 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001431 }
1432)
1433
Colin Cross2207f872021-03-24 12:39:08 -07001434func StubsDefaultsFactory() android.Module {
1435 module := &DocDefaults{}
1436
1437 module.AddProperties(
1438 &JavadocProperties{},
1439 &DroidstubsProperties{},
1440 )
1441
1442 android.InitDefaultsModule(module)
1443
1444 return module
1445}
1446
1447var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1448
1449type PrebuiltStubsSourcesProperties struct {
1450 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001451
1452 // Name of the source soong module that gets shadowed by this prebuilt
1453 // If unspecified, follows the naming convention that the source module of
1454 // the prebuilt is Name() without "prebuilt_" prefix
1455 Source_module_name *string
1456
1457 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1458 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1459 // (without any prebuilt_ prefix)
1460 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1461}
1462
1463func (j *PrebuiltStubsSources) BaseModuleName() string {
1464 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1465}
1466
1467func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1468 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001469}
1470
1471type PrebuiltStubsSources struct {
1472 android.ModuleBase
1473 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001474 embeddableInModuleAndImport
1475
Colin Cross2207f872021-03-24 12:39:08 -07001476 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001477
1478 properties PrebuiltStubsSourcesProperties
1479
kgui67007242022-01-25 13:50:25 +08001480 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001481}
1482
Jihoon Kangee113282024-01-23 00:16:41 +00001483func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1484 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001485}
1486
1487func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001488 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001489 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 -07001490 return
1491 }
1492
Anton Hansson86758ac2021-11-03 14:44:12 +00001493 src := p.properties.Srcs[0]
1494 if filepath.Ext(src) == ".srcjar" {
1495 // This is a srcjar. We can use it directly.
1496 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1497 } else {
1498 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001499
Anton Hansson86758ac2021-11-03 14:44:12 +00001500 // This is a directory. Glob the contents just in case the directory does not exist.
1501 srcGlob := src + "/**/*"
1502 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001503
Anton Hansson86758ac2021-11-03 14:44:12 +00001504 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1505 // the path components are invalid it won't in this case because no components
1506 // are specified and the module directory must exist in order to get this far.
1507 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001508
Anton Hansson86758ac2021-11-03 14:44:12 +00001509 rule := android.NewRuleBuilder(pctx, ctx)
1510 rule.Command().
1511 BuiltTool("soong_zip").
1512 Flag("-write_if_changed").
1513 Flag("-jar").
1514 FlagWithOutput("-o ", outPath).
1515 FlagWithArg("-C ", srcDir.String()).
1516 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1517 rule.Restat()
1518 rule.Build("zip src", "Create srcjar from prebuilt source")
1519 p.stubsSrcJar = outPath
1520 }
mrziwangaa2a2b62024-07-01 12:09:20 -07001521
1522 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
1523 // prebuilt droidstubs does not output "exportable" stubs.
1524 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1525 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
Colin Cross2207f872021-03-24 12:39:08 -07001526}
1527
1528func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1529 return &p.prebuilt
1530}
1531
1532func (p *PrebuiltStubsSources) Name() string {
1533 return p.prebuilt.Name(p.ModuleBase.Name())
1534}
1535
1536// prebuilt_stubs_sources imports a set of java source files as if they were
1537// generated by droidstubs.
1538//
1539// By default, a prebuilt_stubs_sources has a single variant that expects a
1540// set of `.java` files generated by droidstubs.
1541//
1542// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1543// for host modules.
1544//
1545// Intended only for use by sdk snapshots.
1546func PrebuiltStubsSourcesFactory() android.Module {
1547 module := &PrebuiltStubsSources{}
1548
1549 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001550 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001551
1552 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001553 InitDroiddocModule(module, android.HostAndDeviceSupported)
1554 return module
1555}