blob: b30c8448a3ce218053a97f44e411115c6dd9e623 [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 Liu35acd332025-01-24 23:11:22 +000031type StubsInfo struct {
32 ApiVersionsXml android.Path
33 AnnotationsZip android.Path
34 ApiFile android.Path
35 RemovedApiFile android.Path
Yu Liu3a892962025-01-15 23:14:27 +000036}
37
Yu Liucbb50c22025-01-15 20:57:49 +000038type DroidStubsInfo struct {
39 CurrentApiTimestamp android.Path
Yu Liu35acd332025-01-24 23:11:22 +000040 EverythingStubsInfo StubsInfo
41 ExportableStubsInfo StubsInfo
Yu Liucbb50c22025-01-15 20:57:49 +000042}
43
44var DroidStubsInfoProvider = blueprint.NewProvider[DroidStubsInfo]()
45
Yu Liu35acd332025-01-24 23:11:22 +000046type StubsSrcInfo struct {
47 EverythingStubsSrcJar android.Path
48 ExportableStubsSrcJar android.Path
49}
50
51var StubsSrcInfoProvider = blueprint.NewProvider[StubsSrcInfo]()
52
Pedro Loureirocc203502021-10-04 17:24:00 +000053// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070054var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000055
Jihoon Kang6592e872023-12-19 01:13:16 +000056type StubsType int
57
58const (
59 Everything StubsType = iota
60 Runtime
61 Exportable
Jihoon Kang78f89142023-12-27 01:40:29 +000062 Unavailable
Jihoon Kang6592e872023-12-19 01:13:16 +000063)
64
65func (s StubsType) String() string {
66 switch s {
67 case Everything:
68 return "everything"
69 case Runtime:
70 return "runtime"
71 case Exportable:
72 return "exportable"
73 default:
74 return ""
75 }
76}
77
Jihoon Kang5d701272024-02-15 21:53:49 +000078func StringToStubsType(s string) StubsType {
79 switch strings.ToLower(s) {
80 case Everything.String():
81 return Everything
82 case Runtime.String():
83 return Runtime
84 case Exportable.String():
85 return Exportable
86 default:
87 return Unavailable
88 }
89}
90
Colin Cross2207f872021-03-24 12:39:08 -070091func init() {
92 RegisterStubsBuildComponents(android.InitRegistrationContext)
93}
94
95func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
96 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
97
98 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
99 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
100
101 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
102}
103
Jihoon Kangee113282024-01-23 00:16:41 +0000104type stubsArtifacts struct {
105 nullabilityWarningsFile android.WritablePath
106 annotationsZip android.WritablePath
107 apiVersionsXml android.WritablePath
108 metadataZip android.WritablePath
109 metadataDir android.WritablePath
110}
111
Colin Cross2207f872021-03-24 12:39:08 -0700112// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -0700113type Droidstubs struct {
114 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +0000115 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -0700116
Jihoon Kangee113282024-01-23 00:16:41 +0000117 properties DroidstubsProperties
118 apiFile android.Path
119 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -0700120
121 checkCurrentApiTimestamp android.WritablePath
122 updateCurrentApiTimestamp android.WritablePath
123 checkLastReleasedApiTimestamp android.WritablePath
124 apiLintTimestamp android.WritablePath
125 apiLintReport android.WritablePath
126
127 checkNullabilityWarningsTimestamp android.WritablePath
128
Jihoon Kangee113282024-01-23 00:16:41 +0000129 everythingArtifacts stubsArtifacts
130 exportableArtifacts stubsArtifacts
Jihoon Kang3c89f042023-12-19 02:40:22 +0000131
Jihoon Kangee113282024-01-23 00:16:41 +0000132 exportableApiFile android.WritablePath
133 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700134}
135
136type DroidstubsProperties struct {
137 // The generated public API filename by Metalava, defaults to <module>_api.txt
138 Api_filename *string
139
140 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
141 Removed_api_filename *string
142
Colin Cross2207f872021-03-24 12:39:08 -0700143 Check_api struct {
144 Last_released ApiToCheck
145
146 Current ApiToCheck
147
148 Api_lint struct {
149 Enabled *bool
150
151 // If set, performs api_lint on any new APIs not found in the given signature file
152 New_since *string `android:"path"`
153
154 // If not blank, path to the baseline txt file for approved API lint violations.
155 Baseline_file *string `android:"path"`
156 }
157 }
158
159 // user can specify the version of previous released API file in order to do compatibility check.
160 Previous_api *string `android:"path"`
161
162 // is set to true, Metalava will allow framework SDK to contain annotations.
163 Annotations_enabled *bool
164
165 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
166 Merge_annotations_dirs []string
167
168 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
169 Merge_inclusion_annotations_dirs []string
170
171 // a file containing a list of classes to do nullability validation for.
172 Validate_nullability_from_list *string
173
174 // a file containing expected warnings produced by validation of nullability annotations.
175 Check_nullability_warnings *string
176
177 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
178 Create_doc_stubs *bool
179
180 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
181 // Has no effect if create_doc_stubs: true.
182 Output_javadoc_comments *bool
183
184 // if set to false then do not write out stubs. Defaults to true.
185 //
186 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
187 Generate_stubs *bool
188
189 // 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 -0400190 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700191 High_mem *bool
192
satayev783195c2021-06-23 21:49:57 +0100193 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700194 Api_levels_annotations_enabled *bool
195
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000196 // Apply the api levels database created by this module rather than generating one in this droidstubs.
197 Api_levels_module *string
198
Colin Cross2207f872021-03-24 12:39:08 -0700199 // the dirs which Metalava extracts API levels annotations from.
200 Api_levels_annotations_dirs []string
201
Cole Faust051fa912022-10-05 12:45:42 -0700202 // 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 +0100203 Api_levels_sdk_type *string
204
Colin Cross2207f872021-03-24 12:39:08 -0700205 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
206 Api_levels_jar_filename *string
207
208 // if set to true, collect the values used by the Dev tools and
209 // write them in files packaged with the SDK. Defaults to false.
210 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200211
212 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
213 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
214 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000215
216 // API surface of this module. If set, the module contributes to an API surface.
217 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
218 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000219
220 // a list of aconfig_declarations module names that the stubs generated in this module
221 // depend on.
222 Aconfig_declarations []string
Paul Duffin27819362024-07-22 21:03:50 +0100223
224 // List of hard coded filegroups containing Metalava config files that are passed to every
225 // Metalava invocation that this module performs. See addMetalavaConfigFilesToCmd.
226 ConfigFiles []string `android:"path" blueprint:"mutated"`
Colin Cross2207f872021-03-24 12:39:08 -0700227}
228
Anton Hansson52609322021-05-05 10:36:05 +0100229// Used by xsd_config
230type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000231 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100232}
233
234type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000235 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000236}
237
Anton Hansson52609322021-05-05 10:36:05 +0100238// Provider of information about API stubs, used by java_sdk_library.
239type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000240 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100241 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000242 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100243
244 ApiStubsSrcProvider
245}
246
Jihoon Kang063ec002023-06-28 01:16:23 +0000247type currentApiTimestampProvider interface {
248 CurrentApiTimestamp() android.Path
249}
250
Jihoon Kang3c89f042023-12-19 02:40:22 +0000251type annotationFlagsParams struct {
252 migratingNullability bool
253 validatingNullability bool
254 nullabilityWarningsFile android.WritablePath
255 annotationsZip android.WritablePath
256}
257type stubsCommandParams struct {
258 srcJarDir android.ModuleOutPath
259 stubsDir android.OptionalPath
260 stubsSrcJar android.WritablePath
261 metadataZip android.WritablePath
262 metadataDir android.WritablePath
263 apiVersionsXml android.WritablePath
264 nullabilityWarningsFile android.WritablePath
265 annotationsZip android.WritablePath
266 stubConfig stubsCommandConfigParams
267}
268type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000269 stubsType StubsType
270 javaVersion javaVersion
271 deps deps
272 checkApi bool
273 generateStubs bool
274 doApiLint bool
275 doCheckReleased bool
276 writeSdkValues bool
277 migratingNullability bool
278 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000279}
280
Colin Cross2207f872021-03-24 12:39:08 -0700281// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
282// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
283// a droiddoc module to generate documentation.
284func DroidstubsFactory() android.Module {
285 module := &Droidstubs{}
286
287 module.AddProperties(&module.properties,
288 &module.Javadoc.properties)
Paul Duffin27819362024-07-22 21:03:50 +0100289 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Spandan Das2cc80ba2023-10-27 17:21:52 +0000290 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700291
292 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000293
294 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
295 module.createApiContribution(ctx)
296 })
Colin Cross2207f872021-03-24 12:39:08 -0700297 return module
298}
299
300// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
301// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
302// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
303// module when symbols needed by the source files are provided by java_library_host modules.
304func DroidstubsHostFactory() android.Module {
305 module := &Droidstubs{}
306
307 module.AddProperties(&module.properties,
308 &module.Javadoc.properties)
309
Paul Duffin27819362024-07-22 21:03:50 +0100310 module.properties.ConfigFiles = getMetalavaConfigFilegroupReference()
Colin Cross2207f872021-03-24 12:39:08 -0700311 InitDroiddocModule(module, android.HostSupported)
312 return module
313}
314
Jihoon Kang246690a2024-02-01 21:55:01 +0000315func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000316 switch stubsType {
317 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000318 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000319 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000320 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000321 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000322 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000323 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000324 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000325}
326
Jihoon Kang246690a2024-02-01 21:55:01 +0000327func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000328 switch stubsType {
329 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000330 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000331 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000332 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000333 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000334 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000335 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000336 if ret == nil && err == nil {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000337 err = fmt.Errorf("api file is null for the stub type %s", stubsType.String())
Jihoon Kang246690a2024-02-01 21:55:01 +0000338 }
339 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000340}
341
Jihoon Kang246690a2024-02-01 21:55:01 +0000342func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000343 switch stubsType {
344 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000345 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000346 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000347 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000348 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000349 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 +0000350 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000351 if ret == nil && err == nil {
352 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
353 }
354 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000355}
356
Jihoon Kang246690a2024-02-01 21:55:01 +0000357func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000358 switch stubsType {
359 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000360 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000361 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000362 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000363 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000364 if ret == nil && err == nil {
365 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
366 }
367 return ret, err
368}
369
370func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
371 switch stubsType {
372 case Everything:
373 ret, err = d.removedApiFile, nil
374 case Exportable:
375 ret, err = d.exportableRemovedApiFile, nil
376 default:
377 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
378 }
379 if ret == nil && err == nil {
380 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
381 }
382 return ret, err
383}
384
385func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
386 switch stubsType {
387 case Everything:
388 ret, err = d.stubsSrcJar, nil
389 case Exportable:
390 ret, err = d.exportableStubsSrcJar, nil
391 default:
392 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
393 }
394 if ret == nil && err == nil {
395 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
396 }
397 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000398}
399
Jihoon Kang063ec002023-06-28 01:16:23 +0000400func (d *Droidstubs) CurrentApiTimestamp() android.Path {
401 return d.checkCurrentApiTimestamp
402}
403
Colin Cross2207f872021-03-24 12:39:08 -0700404var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
405var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
406var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000407var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000408var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700409
410func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
411 d.Javadoc.addDeps(ctx)
412
413 if len(d.properties.Merge_annotations_dirs) != 0 {
414 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
415 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
416 }
417 }
418
419 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
420 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
421 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
422 }
423 }
424
425 if len(d.properties.Api_levels_annotations_dirs) != 0 {
426 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
427 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
428 }
429 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000430
Jihoon Kang6592e872023-12-19 01:13:16 +0000431 if len(d.properties.Aconfig_declarations) != 0 {
432 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
433 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
434 }
435 }
436
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000437 if d.properties.Api_levels_module != nil {
438 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
439 }
Colin Cross2207f872021-03-24 12:39:08 -0700440}
441
Jihoon Kang3c89f042023-12-19 02:40:22 +0000442func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
443 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
444}
445
446func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000447
Jihoon Kang36c3d962024-03-14 17:28:44 +0000448 apiFileName := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
449 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), apiFileName)
450 cmd.FlagWithOutput("--api ", uncheckedApiFile)
451 if checkApi || String(d.properties.Api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000452 if stubsType == Everything {
453 d.apiFile = uncheckedApiFile
454 } else if stubsType == Exportable {
455 d.exportableApiFile = uncheckedApiFile
456 }
Colin Cross2207f872021-03-24 12:39:08 -0700457 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000458 if stubsType == Everything {
459 // If check api is disabled then make the source file available for export.
460 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
461 } else if stubsType == Exportable {
462 d.exportableApiFile = uncheckedApiFile
463 }
Colin Cross2207f872021-03-24 12:39:08 -0700464 }
465
Jihoon Kang36c3d962024-03-14 17:28:44 +0000466 removedApiFileName := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
467 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), removedApiFileName)
468 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000469 if checkApi || String(d.properties.Removed_api_filename) != "" {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000470 if stubsType == Everything {
471 d.removedApiFile = uncheckedRemovedFile
472 } else if stubsType == Exportable {
473 d.exportableRemovedApiFile = uncheckedRemovedFile
474 }
Colin Cross2207f872021-03-24 12:39:08 -0700475 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
Jihoon Kang36c3d962024-03-14 17:28:44 +0000476 if stubsType == Everything {
477 // If check api is disabled then make the source removed api file available for export.
478 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
479 } else if stubsType == Exportable {
480 d.exportableRemovedApiFile = uncheckedRemovedFile
481 }
Colin Cross2207f872021-03-24 12:39:08 -0700482 }
483
Colin Cross2207f872021-03-24 12:39:08 -0700484 if stubsDir.Valid() {
485 if Bool(d.properties.Create_doc_stubs) {
486 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
487 } else {
488 cmd.FlagWithArg("--stubs ", stubsDir.String())
489 if !Bool(d.properties.Output_javadoc_comments) {
490 cmd.Flag("--exclude-documentation-from-stubs")
491 }
492 }
493 }
494}
495
Jihoon Kang3c89f042023-12-19 02:40:22 +0000496func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000497 if Bool(d.properties.Annotations_enabled) {
498 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100499
Jihoon Kanga11d6792024-03-05 16:12:20 +0000500 if params.migratingNullability {
Jihoon Kang5623e542024-01-31 23:27:26 +0000501 previousApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Previous_api)})
502 cmd.FlagForEachInput("--migrate-nullness ", previousApiFiles)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000503 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000504
Jihoon Kanga11d6792024-03-05 16:12:20 +0000505 if s := String(d.properties.Validate_nullability_from_list); s != "" {
506 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
507 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000508
Jihoon Kanga11d6792024-03-05 16:12:20 +0000509 if params.validatingNullability {
510 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
511 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000512
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000513 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000514
Jihoon Kanga11d6792024-03-05 16:12:20 +0000515 if len(d.properties.Merge_annotations_dirs) != 0 {
516 d.mergeAnnoDirFlags(ctx, cmd)
517 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000518
Jihoon Kanga11d6792024-03-05 16:12:20 +0000519 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700520 }
Colin Cross2207f872021-03-24 12:39:08 -0700521}
522
523func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Yu Liu3a892962025-01-15 23:14:27 +0000524 ctx.VisitDirectDepsProxyWithTag(metalavaMergeAnnotationsDirTag, func(m android.ModuleProxy) {
525 if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
526 cmd.FlagWithArg("--merge-qualifier-annotations ", t.Dir.String()).Implicits(t.Deps)
Colin Cross2207f872021-03-24 12:39:08 -0700527 } else {
528 ctx.PropertyErrorf("merge_annotations_dirs",
529 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
530 }
531 })
532}
533
534func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Yu Liu3a892962025-01-15 23:14:27 +0000535 ctx.VisitDirectDepsProxyWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.ModuleProxy) {
536 if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
537 cmd.FlagWithArg("--merge-inclusion-annotations ", t.Dir.String()).Implicits(t.Deps)
Colin Cross2207f872021-03-24 12:39:08 -0700538 } else {
539 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
540 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
541 }
542 })
543}
544
Jihoon Kanga11d6792024-03-05 16:12:20 +0000545func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000546 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000547 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000548 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000549 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000550 } else {
Yu Liu3a892962025-01-15 23:14:27 +0000551 ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsModuleTag, func(m android.ModuleProxy) {
552 if s, ok := android.OtherModuleProvider(ctx, m, DroidStubsInfoProvider); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000553 if stubsType == Everything {
Yu Liu35acd332025-01-24 23:11:22 +0000554 apiVersions = s.EverythingStubsInfo.ApiVersionsXml
Jihoon Kangd9a06942024-01-26 01:49:20 +0000555 } else if stubsType == Exportable {
Yu Liu35acd332025-01-24 23:11:22 +0000556 apiVersions = s.ExportableStubsInfo.ApiVersionsXml
Jihoon Kangd9a06942024-01-26 01:49:20 +0000557 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000558 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000559 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000560 } else {
561 ctx.PropertyErrorf("api_levels_module",
562 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
563 }
564 })
Colin Cross2207f872021-03-24 12:39:08 -0700565 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000566 if apiVersions != nil {
MÃ¥rten Kongstad13ae6872025-02-18 16:58:36 +0100567 // We are migrating from a single API level to major.minor
568 // versions and PlatformSdkVersionFull is not yet set in all
569 // release configs. If it is not set, fall back on the single
570 // API level.
571 if fullSdkVersion := ctx.Config().PlatformSdkVersionFull(); len(fullSdkVersion) > 0 {
572 cmd.FlagWithArg("--current-version ", fullSdkVersion)
573 } else {
574 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
575 }
MÃ¥rten Kongstad8585cd02025-03-12 21:08:30 +0100576 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000577 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
578 }
579}
Colin Cross2207f872021-03-24 12:39:08 -0700580
Paul Duffin5a195f42024-05-01 12:52:35 +0100581// AndroidPlusUpdatableJar is the name of some extra jars added into `module-lib` and
582// `system-server` directories that contain all the APIs provided by the platform and updatable
583// modules because the `android.jar` files do not. See b/337836752.
584const AndroidPlusUpdatableJar = "android-plus-updatable.jar"
585
Jihoon Kang3c89f042023-12-19 02:40:22 +0000586func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700587 if len(d.properties.Api_levels_annotations_dirs) == 0 {
588 ctx.PropertyErrorf("api_levels_annotations_dirs",
589 "has to be non-empty if api levels annotations was enabled!")
590 }
591
Jihoon Kang3c89f042023-12-19 02:40:22 +0000592 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700593
594 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
595
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100596 // TODO: Avoid the duplication of API surfaces, reuse apiScope.
597 // Add all relevant --android-jar-pattern patterns for Metalava.
598 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
599 // an actual file present on disk (in the order the patterns were passed). For system APIs for
600 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
601 // for older releases. Similarly, module-lib falls back to system API.
602 var sdkDirs []string
Paul Duffin92efc612024-05-02 17:18:05 +0100603 apiLevelsSdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public")
604 switch apiLevelsSdkType {
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100605 case "system-server":
606 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
607 case "module-lib":
608 sdkDirs = []string{"module-lib", "system", "public"}
609 case "system":
610 sdkDirs = []string{"system", "public"}
611 case "public":
612 sdkDirs = []string{"public"}
613 default:
614 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
615 return
616 }
617
Paul Duffin92efc612024-05-02 17:18:05 +0100618 // Construct a pattern to match the appropriate extensions that should be included in the
619 // generated api-versions.xml file.
620 //
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100621 // Use the first item in the sdkDirs array as that is the sdk type for the target API levels
622 // being generated but has the advantage over `Api_levels_sdk_type` as it has been validated.
Paul Duffin92efc612024-05-02 17:18:05 +0100623 // The exception is for system-server which needs to include module-lib and system-server. That
624 // is because while system-server extends module-lib the system-server extension directory only
625 // contains service-* modules which provide system-server APIs it does not list the modules which
626 // only provide a module-lib, so they have to be included separately.
627 extensionSurfacesPattern := sdkDirs[0]
628 if apiLevelsSdkType == "system-server" {
629 // Take the first two items in sdkDirs, which are system-server and module-lib, and construct
630 // a pattern that will match either.
631 extensionSurfacesPattern = strings.Join(sdkDirs[0:2], "|")
632 }
633 extensionsPattern := fmt.Sprintf(`/extensions/[0-9]+/(%s)/.*\.jar`, extensionSurfacesPattern)
Paul Duffin58cfc9a2024-04-25 17:01:49 +0100634
satayev783195c2021-06-23 21:49:57 +0100635 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200636 var extensions_dir string
Yu Liu3a892962025-01-15 23:14:27 +0000637 ctx.VisitDirectDepsProxyWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.ModuleProxy) {
638 if t, ok := android.OtherModuleProvider(ctx, m, ExportedDroiddocDirInfoProvider); ok {
639 extRegex := regexp.MustCompile(t.Dir.String() + extensionsPattern)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200640
641 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
642 // ideally this should be read from prebuiltApis.properties.Extensions_*
Yu Liu3a892962025-01-15 23:14:27 +0000643 for _, dep := range t.Deps {
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100644 // Check to see if it matches an extension first.
645 depBase := dep.Base()
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200646 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
647 if extensions_dir == "" {
Yu Liu3a892962025-01-15 23:14:27 +0000648 extensions_dir = t.Dir.String() + "/extensions"
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200649 }
650 cmd.Implicit(dep)
Paul Duffin2ced2eb2024-05-01 13:13:51 +0100651 } else if depBase == filename {
652 // 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 -0700653 cmd.Implicit(dep)
Paul Duffin5a195f42024-05-01 12:52:35 +0100654 } else if depBase == AndroidPlusUpdatableJar && d.properties.Extensions_info_file != nil {
655 // The output api-versions.xml has been requested to include information on SDK
Paul Duffinee5e0932025-01-15 18:00:35 +0000656 // extensions, i.e. updatable Apis. That means it also needs to include the history of
657 // those updatable APIs. Usually, they would be included in the `android.jar` file but
658 // unfortunately, the `module-lib` and `system-server` cannot as it would lead to build
659 // cycles. So, the module-lib and system-server directories contain an
660 // `android-plus-updatable.jar` that should be used instead of `android.jar`. See
661 // AndroidPlusUpdatableJar for more information.
Paul Duffin5a195f42024-05-01 12:52:35 +0100662 cmd.Implicit(dep)
Colin Cross2207f872021-03-24 12:39:08 -0700663 }
664 }
satayev783195c2021-06-23 21:49:57 +0100665
Yu Liu3a892962025-01-15 23:14:27 +0000666 dirs = append(dirs, t.Dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700667 } else {
668 ctx.PropertyErrorf("api_levels_annotations_dirs",
669 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
670 }
671 })
satayev783195c2021-06-23 21:49:57 +0100672
Paul Duffin5a195f42024-05-01 12:52:35 +0100673 // Generate the list of --android-jar-pattern options. The order matters so the first one which
Paul Duffin4c9d3052025-01-07 16:03:10 +0000674 // matches will be the one that is used for a specific api level.
Pedro Loureirocc203502021-10-04 17:24:00 +0000675 for _, sdkDir := range sdkDirs {
676 for _, dir := range dirs {
Paul Duffin5a195f42024-05-01 12:52:35 +0100677 addPattern := func(jarFilename string) {
Paul Duffin9820c1a2025-01-20 10:35:45 +0000678 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:major.minor?}/%s/%s", dir, sdkDir, jarFilename))
Paul Duffin5a195f42024-05-01 12:52:35 +0100679 }
680
681 if sdkDir == "module-lib" || sdkDir == "system-server" {
682 // The module-lib and system-server android.jars do not include the updatable modules (as
683 // doing so in the source would introduce dependency cycles and the prebuilts have to
684 // match the sources). So, instead an additional `android-plus-updatable.jar` will be used
685 // that does include the updatable modules and this pattern will match that. This pattern
686 // is added in addition to the following pattern to decouple this change from the change
687 // to add the `android-plus-updatable.jar`.
688 addPattern(AndroidPlusUpdatableJar)
689 }
690
691 addPattern(filename)
Pedro Loureirocc203502021-10-04 17:24:00 +0000692 }
Paul Duffin4f707292025-01-16 14:12:31 +0000693
694 if extensions_dir != "" {
695 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/{version:extension}/%s/{module}.jar", extensions_dir, sdkDir))
696 }
satayev783195c2021-06-23 21:49:57 +0100697 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200698
699 if d.properties.Extensions_info_file != nil {
700 if extensions_dir == "" {
701 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
702 }
703 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
704 cmd.Implicit(info_file)
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200705 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
706 }
Colin Cross2207f872021-03-24 12:39:08 -0700707}
708
Jihoon Kang472f73f2024-03-28 20:59:29 +0000709func (d *Droidstubs) apiCompatibilityFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType) {
710 if len(d.Javadoc.properties.Out) > 0 {
711 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
712 }
713
Jihoon Kang5623e542024-01-31 23:27:26 +0000714 apiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Api_file)})
715 removedApiFiles := android.PathsForModuleSrc(ctx, []string{String(d.properties.Check_api.Last_released.Removed_api_file)})
Jihoon Kang472f73f2024-03-28 20:59:29 +0000716
Jihoon Kang5623e542024-01-31 23:27:26 +0000717 cmd.FlagForEachInput("--check-compatibility:api:released ", apiFiles)
718 cmd.FlagForEachInput("--check-compatibility:removed:released ", removedApiFiles)
Jihoon Kang472f73f2024-03-28 20:59:29 +0000719
720 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
721 if baselineFile.Valid() {
722 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
723 }
724}
725
Colin Crosse52c2ac2022-03-28 17:03:35 -0700726func metalavaUseRbe(ctx android.ModuleContext) bool {
727 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
728}
729
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000730func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths,
Paul Duffind71dc402025-01-24 16:10:09 +0000731 srcJarList android.Path, homeDir android.WritablePath, params stubsCommandConfigParams,
732 configFiles android.Paths, apiSurface *string) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700733 rule.Command().Text("rm -rf").Flag(homeDir.String())
734 rule.Command().Text("mkdir -p").Flag(homeDir.String())
735
Anton Hansson556e8142021-06-04 16:20:25 +0100736 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700737 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
738
Colin Crosse52c2ac2022-03-28 17:03:35 -0700739 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700740 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700741 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000742 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
743 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700744 labels := map[string]string{"type": "tool", "name": "metalava"}
745 // TODO: metalava pool rejects these jobs
746 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
747 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000748 Labels: labels,
749 ExecStrategy: execStrategy,
750 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
751 Platform: map[string]string{remoteexec.PoolKey: pool},
752 Compare: compare,
753 NumLocalRuns: 1,
754 NumRemoteRuns: 1,
755 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700756 })
Colin Cross2207f872021-03-24 12:39:08 -0700757 }
758
Colin Cross6aa5c402021-03-24 12:28:50 -0700759 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700760 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400761 Flag(config.MetalavaAddOpens).
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000762 FlagWithArg("--java-source ", params.javaVersion.String()).
763 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, fmt.Sprintf("%s.metalava.rsp", params.stubsType.String())), srcs).
Colin Cross2207f872021-03-24 12:39:08 -0700764 FlagWithInput("@", srcJarList)
765
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100766 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
767 // years, so it is unlikely to change any time soon.
Jihoon Kang421c1cd2024-04-22 21:17:12 +0000768 combinedPaths := append(([]android.Path)(nil), params.deps.bootClasspath.Paths()...)
769 combinedPaths = append(combinedPaths, params.deps.classpath.Paths()...)
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100770 if len(combinedPaths) > 0 {
771 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700772 }
773
Liz Kammere09e20e2023-10-16 15:07:54 -0400774 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000775
Paul Duffin27819362024-07-22 21:03:50 +0100776 addMetalavaConfigFilesToCmd(cmd, configFiles)
777
Paul Duffind71dc402025-01-24 16:10:09 +0000778 addOptionalApiSurfaceToCmd(cmd, apiSurface)
779
Colin Cross2207f872021-03-24 12:39:08 -0700780 return cmd
781}
782
Paul Duffin27819362024-07-22 21:03:50 +0100783// MetalavaConfigFilegroup is the name of the filegroup in build/soong/java/metalava that lists
784// the configuration files to pass to Metalava.
785const MetalavaConfigFilegroup = "metalava-config-files"
786
787// Get a reference to the MetalavaConfigFilegroup suitable for use in a property.
788func getMetalavaConfigFilegroupReference() []string {
789 return []string{":" + MetalavaConfigFilegroup}
790}
791
792// addMetalavaConfigFilesToCmd adds --config-file options to use the config files list in the
793// MetalavaConfigFilegroup filegroup.
794func addMetalavaConfigFilesToCmd(cmd *android.RuleBuilderCommand, configFiles android.Paths) {
795 cmd.FlagForEachInput("--config-file ", configFiles)
796}
797
Paul Duffind71dc402025-01-24 16:10:09 +0000798// addOptionalApiSurfaceToCmd adds --api-surface option is apiSurface is not `nil`.
799func addOptionalApiSurfaceToCmd(cmd *android.RuleBuilderCommand, apiSurface *string) {
800 if apiSurface != nil {
801 cmd.Flag("--api-surface")
802 cmd.Flag(*apiSurface)
803 }
804}
805
Jihoon Kang3c89f042023-12-19 02:40:22 +0000806// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
807// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
808// property is defined, apply transformations and only revert the flagged apis that are not
809// enabled via release configurations and are not specified in aconfig_declarations
Jihoon Kang5d701272024-02-15 21:53:49 +0000810func generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
Jihoon Kang6592e872023-12-19 01:13:16 +0000811 var filterArgs string
812 switch stubsType {
813 // No flagged apis specific flags need to be passed to metalava when generating
814 // everything stubs
815 case Everything:
816 return
817
818 case Runtime:
819 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
820
821 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000822 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
823 // the flagged apis that have read_write permissions are exposed on top of the enabled
824 // and read_only apis. This is to support local override of flag values at runtime.
825 if ctx.Config().ReleaseExportRuntimeApis() {
826 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
827 } else {
828 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
829 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000830 }
831
Paul Duffin50243ae2025-03-03 19:10:27 +0000832 // If aconfigFlagsPaths is empty then it is still important to generate the
833 // Metalava flags config file, albeit with an empty set of flags, so that all
834 // flagged APIs will be reverted.
Jihoon Kangf1e0ff02024-11-20 21:10:40 +0000835
Paul Duffin50243ae2025-03-03 19:10:27 +0000836 releasedFlagsFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flags-%s.pb", stubsType.String()))
837 metalavaFlagsConfigFile := android.PathForModuleOut(ctx, fmt.Sprintf("flags-config-%s.xml", stubsType.String()))
Jihoon Kangf1e0ff02024-11-20 21:10:40 +0000838
Jihoon Kang6592e872023-12-19 01:13:16 +0000839 ctx.Build(pctx, android.BuildParams{
840 Rule: gatherReleasedFlaggedApisRule,
841 Inputs: aconfigFlagsPaths,
Paul Duffin50243ae2025-03-03 19:10:27 +0000842 Output: releasedFlagsFile,
Jihoon Kang6592e872023-12-19 01:13:16 +0000843 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,
Paul Duffin50243ae2025-03-03 19:10:27 +0000852 Input: releasedFlagsFile,
853 Output: metalavaFlagsConfigFile,
854 Description: fmt.Sprintf("%s metalava flags config", stubsType),
Jihoon Kang6592e872023-12-19 01:13:16 +0000855 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000856
Paul Duffin50243ae2025-03-03 19:10:27 +0000857 cmd.FlagWithInput("--config-file ", metalavaFlagsConfigFile)
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")
Paul Duffin27819362024-07-22 21:03:50 +0100875
876 configFiles := android.PathsForModuleSrc(ctx, d.properties.ConfigFiles)
877
Paul Duffind71dc402025-01-24 16:10:09 +0000878 cmd := metalavaCmd(ctx, rule, d.Javadoc.srcFiles, srcJarList, homeDir, params.stubConfig,
879 configFiles, d.properties.Api_surface)
Colin Cross2207f872021-03-24 12:39:08 -0700880 cmd.Implicits(d.Javadoc.implicits)
881
Jihoon Kang3c89f042023-12-19 02:40:22 +0000882 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700883
Jihoon Kang3c89f042023-12-19 02:40:22 +0000884 if params.stubConfig.writeSdkValues {
885 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
886 }
887
888 annotationParams := annotationFlagsParams{
889 migratingNullability: params.stubConfig.migratingNullability,
890 validatingNullability: params.stubConfig.validatingNullability,
891 nullabilityWarningsFile: params.nullabilityWarningsFile,
892 annotationsZip: params.annotationsZip,
893 }
894
Jihoon Kanga11d6792024-03-05 16:12:20 +0000895 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700896 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000897 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700898
Jihoon Kang472f73f2024-03-28 20:59:29 +0000899 if params.stubConfig.doCheckReleased {
900 d.apiCompatibilityFlags(ctx, cmd, params.stubConfig.stubsType)
901 }
902
Colin Crossbc139922021-03-25 18:33:16 -0700903 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700904
Colin Cross2207f872021-03-24 12:39:08 -0700905 for _, o := range d.Javadoc.properties.Out {
906 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
907 }
908
Jihoon Kang3c89f042023-12-19 02:40:22 +0000909 return cmd
910}
Colin Cross2207f872021-03-24 12:39:08 -0700911
Jihoon Kang3c89f042023-12-19 02:40:22 +0000912// Sandbox rule for generating the everything stubs and other artifacts
913func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
914 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
915 rule := android.NewRuleBuilder(pctx, ctx)
916 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
917 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
918 SandboxInputs()
919
920 var stubsDir android.OptionalPath
921 if params.generateStubs {
922 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
923 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
924 }
925
926 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000927 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
928 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000929 }
930
Jihoon Kanga11d6792024-03-05 16:12:20 +0000931 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000932 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000933 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000934 }
Jihoon Kangee113282024-01-23 00:16:41 +0000935 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000936 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000937 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000938 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000939 }
940
941 commonCmdParams := stubsCommandParams{
942 srcJarDir: srcJarDir,
943 stubsDir: stubsDir,
944 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000945 metadataDir: d.everythingArtifacts.metadataDir,
946 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
947 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
948 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000949 stubConfig: params,
950 }
951
952 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
953
954 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
955
956 if params.generateStubs {
957 rule.Command().
958 BuiltTool("soong_zip").
959 Flag("-write_if_changed").
960 Flag("-jar").
961 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
962 FlagWithArg("-C ", stubsDir.String()).
963 FlagWithArg("-D ", stubsDir.String())
964 }
965
966 if params.writeSdkValues {
967 rule.Command().
968 BuiltTool("soong_zip").
969 Flag("-write_if_changed").
970 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000971 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
972 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
973 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000974 }
975
976 // TODO: We don't really need two separate API files, but this is a reminiscence of how
977 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
978 if params.doApiLint {
979 rule.Command().Text("touch").Output(d.apiLintTimestamp)
980 }
981 if params.doCheckReleased {
982 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
983 }
984
985 // TODO(b/183630617): rewrapper doesn't support restat rules
986 if !metalavaUseRbe(ctx) {
987 rule.Restat()
988 }
989
990 zipSyncCleanupCmd(rule, srcJarDir)
991
992 rule.Build("metalava", "metalava merged")
993}
994
995// Sandbox rule for generating the everything artifacts that are not run by
996// default but only run based on the module configurations
997func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700998
999 // Add API lint options.
Paul Duffinbaf34782024-05-28 17:27:22 +01001000 treatDocumentationIssuesAsErrors := false
Jihoon Kang3c89f042023-12-19 02:40:22 +00001001 if doApiLint {
Jihoon Kang5623e542024-01-31 23:27:26 +00001002 var newSince android.Paths
1003 if d.properties.Check_api.Api_lint.New_since != nil {
1004 newSince = android.PathsForModuleSrc(ctx, []string{proptools.String(d.properties.Check_api.Api_lint.New_since)})
1005 }
Paul Duffin0a71d732024-04-22 13:22:56 +01001006 cmd.Flag("--api-lint")
1007 cmd.FlagForEachInput("--api-lint-previous-api ", newSince)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001008 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001009 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
1010
Paul Duffinc540bee2024-08-29 15:35:58 +01001011 // If UnflaggedApi issues have not already been configured then make sure that existing
1012 // UnflaggedApi issues are reported as warnings but issues in new/changed code are treated as
1013 // errors by the Build Warnings Aye Aye Analyzer in Gerrit.
Paul Duffin88d3b392024-08-28 17:37:36 +01001014 // Once existing issues have been fixed this will be changed to error.
Paul Duffinc540bee2024-08-29 15:35:58 +01001015 // TODO(b/362771529): Switch to --error
1016 if !strings.Contains(cmd.String(), " UnflaggedApi ") {
1017 cmd.Flag("--error-when-new UnflaggedApi")
1018 }
Paul Duffin88d3b392024-08-28 17:37:36 +01001019
Colin Cross0d532412021-03-25 09:38:45 -07001020 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -07001021 if d.Name() != "android.car-system-stubs-docs" &&
1022 d.Name() != "android.car-stubs-docs" {
Paul Duffinbaf34782024-05-28 17:27:22 +01001023 treatDocumentationIssuesAsErrors = true
Colin Cross2207f872021-03-24 12:39:08 -07001024 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
1025 }
1026
1027 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001028 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
1029 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001030
1031 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -07001032 //
1033 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
1034 // message and metalava's one?
1035 msg := `$'` + // Enclose with $' ... '
1036 `************************************************************\n` +
1037 `Your API changes are triggering API Lint warnings or errors.\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001038 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001039 `To make the failures go away:\n` +
Colin Cross2207f872021-03-24 12:39:08 -07001040 `\n` +
Adrian Roos40be6472024-11-05 14:25:35 +00001041 `1. REQUIRED: Read the messages carefully and address them by` +
1042 ` fixing the API if appropriate.\n` +
1043 `2. If the failure is a false positive, you can suppress it with:\n` +
1044 ` @SuppressLint("<id>")\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +00001045 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -07001046
1047 if baselineFile.Valid() {
1048 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1049 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
1050
1051 msg += fmt.Sprintf(``+
Cole Faust5146e782024-11-15 14:47:49 -08001052 `3. FOR LSC ONLY: You can update the baseline by executing\n`+
Adrian Roos40be6472024-11-05 14:25:35 +00001053 ` the following command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -07001054 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
1055 ` "%s" \\\n`+
1056 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001057 ` To submit the revised baseline.txt to the main Android\n`+
1058 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
1059 } else {
1060 msg += fmt.Sprintf(``+
Adrian Roos40be6472024-11-05 14:25:35 +00001061 `3. FOR LSC ONLY: You can add a baseline file of existing lint failures\n`+
Colin Cross2207f872021-03-24 12:39:08 -07001062 ` to the build rule of %s.\n`, d.Name())
1063 }
1064 // Note the message ends with a ' (single quote), to close the $' ... ' .
1065 msg += `************************************************************\n'`
1066
1067 cmd.FlagWithArg("--error-message:api-lint ", msg)
1068 }
1069
Paul Duffinbaf34782024-05-28 17:27:22 +01001070 if !treatDocumentationIssuesAsErrors {
Paul Duffinb679bdd2024-06-10 14:29:41 +01001071 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffinbaf34782024-05-28 17:27:22 +01001072 }
1073
Colin Cross2207f872021-03-24 12:39:08 -07001074 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001075 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -07001076 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001077 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001078 if baselineFile.Valid() {
Jihoon Kang472f73f2024-03-28 20:59:29 +00001079 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -07001080 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1081 }
Colin Cross2207f872021-03-24 12:39:08 -07001082 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1083 msg := `$'\n******************************\n` +
1084 `You have tried to change the API from what has been previously released in\n` +
1085 `an SDK. Please fix the errors listed above.\n` +
1086 `******************************\n'`
1087
1088 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1089 }
1090
Paul Duffin10a23c22023-08-11 22:47:31 +01001091 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1092 // Pass the current API file into metalava so it can use it as the basis for determining how to
1093 // generate the output signature files (both api and removed).
1094 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1095 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1096 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001097}
Paul Duffin10a23c22023-08-11 22:47:31 +01001098
Paul Duffinb679bdd2024-06-10 14:29:41 +01001099// HIDDEN_DOCUMENTATION_ISSUES is the set of documentation related issues that should always be
1100// hidden as they are very noisy and provide little value.
1101var HIDDEN_DOCUMENTATION_ISSUES = []string{
1102 "Deprecated",
1103 "IntDef",
1104 "Nullable",
1105}
1106
1107func treatDocumentationIssuesAsWarningErrorWhenNew(cmd *android.RuleBuilderCommand) {
1108 // Treat documentation issues as warnings, but error when new.
1109 cmd.Flag("--error-when-new-category").Flag("Documentation")
1110
1111 // Hide some documentation issues that generated a lot of noise for little benefit.
1112 cmd.FlagForEachArg("--hide ", HIDDEN_DOCUMENTATION_ISSUES)
1113}
1114
Jihoon Kang3c89f042023-12-19 02:40:22 +00001115// Sandbox rule for generating exportable stubs and other artifacts
1116func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1117 optionalCmdParams := stubsCommandParams{
1118 stubConfig: params,
1119 }
1120
Jihoon Kang246690a2024-02-01 21:55:01 +00001121 if params.generateStubs {
1122 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1123 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1124 }
1125
Jihoon Kang3c89f042023-12-19 02:40:22 +00001126 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001127 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1128 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1129 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1130 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001131 }
1132
Jihoon Kanga11d6792024-03-05 16:12:20 +00001133 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001134 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001135 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1136 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001137 }
Jihoon Kangee113282024-01-23 00:16:41 +00001138 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1139 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001140 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001141 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001142 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1143 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001144 }
1145
1146 if params.checkApi || String(d.properties.Api_filename) != "" {
1147 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1148 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1149 }
1150
1151 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1152 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1153 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1154 }
1155
1156 d.optionalStubCmd(ctx, optionalCmdParams)
1157}
1158
1159func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1160
1161 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1162 rule := android.NewRuleBuilder(pctx, ctx)
1163 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1164 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1165 SandboxInputs()
1166
1167 if params.stubConfig.generateStubs {
1168 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1169 }
1170
1171 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1172
Jihoon Kang5d701272024-02-15 21:53:49 +00001173 generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
Jihoon Kang3c89f042023-12-19 02:40:22 +00001174
1175 if params.stubConfig.doApiLint {
1176 // Pass the lint baseline file as an input to resolve the lint errors.
1177 // The exportable stubs generation does not update the lint baseline file.
1178 // Lint baseline file update is handled by the everything stubs
1179 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1180 if baselineFile.Valid() {
1181 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1182 }
1183 }
1184
Paul Duffin71527b72024-05-31 13:30:32 +01001185 // Treat documentation issues as warnings, but error when new.
Paul Duffinb679bdd2024-06-10 14:29:41 +01001186 treatDocumentationIssuesAsWarningErrorWhenNew(cmd)
Paul Duffin71527b72024-05-31 13:30:32 +01001187
Jihoon Kang3c89f042023-12-19 02:40:22 +00001188 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001189 rule.Command().
1190 BuiltTool("soong_zip").
1191 Flag("-write_if_changed").
1192 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001193 FlagWithOutput("-o ", params.stubsSrcJar).
1194 FlagWithArg("-C ", params.stubsDir.String()).
1195 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001196 }
1197
Jihoon Kang3c89f042023-12-19 02:40:22 +00001198 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001199 rule.Command().
1200 BuiltTool("soong_zip").
1201 Flag("-write_if_changed").
1202 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001203 FlagWithOutput("-o ", params.metadataZip).
1204 FlagWithArg("-C ", params.metadataDir.String()).
1205 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001206 }
1207
Colin Cross6aa5c402021-03-24 12:28:50 -07001208 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001209 if !metalavaUseRbe(ctx) {
1210 rule.Restat()
1211 }
Colin Cross2207f872021-03-24 12:39:08 -07001212
Jihoon Kang3c89f042023-12-19 02:40:22 +00001213 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001214
Jihoon Kang3c89f042023-12-19 02:40:22 +00001215 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1216}
1217
Jihoon Kange9eecc72025-01-28 18:57:18 +00001218func (d *Droidstubs) setPhonyRules(ctx android.ModuleContext) {
1219 if d.apiFile != nil {
1220 ctx.Phony(d.Name(), d.apiFile)
1221 ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.apiFile)
1222 }
1223 if d.removedApiFile != nil {
1224 ctx.Phony(d.Name(), d.removedApiFile)
1225 ctx.Phony(fmt.Sprintf("%s.txt", d.Name()), d.removedApiFile)
1226 }
1227 if d.checkCurrentApiTimestamp != nil {
1228 ctx.Phony(fmt.Sprintf("%s-check-current-api", d.Name()), d.checkCurrentApiTimestamp)
1229 ctx.Phony("checkapi", d.checkCurrentApiTimestamp)
Jihoon Kange9eecc72025-01-28 18:57:18 +00001230 }
1231 if d.updateCurrentApiTimestamp != nil {
1232 ctx.Phony(fmt.Sprintf("%s-update-current-api", d.Name()), d.updateCurrentApiTimestamp)
1233 ctx.Phony("update-api", d.updateCurrentApiTimestamp)
1234 }
1235 if d.checkLastReleasedApiTimestamp != nil {
1236 ctx.Phony(fmt.Sprintf("%s-check-last-released-api", d.Name()), d.checkLastReleasedApiTimestamp)
Jihoon Kange9eecc72025-01-28 18:57:18 +00001237 }
1238 if d.apiLintTimestamp != nil {
1239 ctx.Phony(fmt.Sprintf("%s-api-lint", d.Name()), d.apiLintTimestamp)
Jihoon Kange9eecc72025-01-28 18:57:18 +00001240 }
1241 if d.checkNullabilityWarningsTimestamp != nil {
1242 ctx.Phony(fmt.Sprintf("%s-check-nullability-warnings", d.Name()), d.checkNullabilityWarningsTimestamp)
Jihoon Kange9eecc72025-01-28 18:57:18 +00001243 }
1244}
1245
Jihoon Kang3c89f042023-12-19 02:40:22 +00001246func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1247 deps := d.Javadoc.collectDeps(ctx)
1248
1249 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1250 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1251
1252 // Add options for the other optional tasks: API-lint and check-released.
1253 // We generate separate timestamp files for them.
LaMont Jonesec1b7fa2025-03-05 11:57:40 -08001254 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) && !ctx.Config().PartialCompileFlags().Disable_api_lint
Jihoon Kang3c89f042023-12-19 02:40:22 +00001255 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1256
1257 writeSdkValues := Bool(d.properties.Write_sdk_values)
1258
1259 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1260
1261 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1262 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1263 String(d.properties.Validate_nullability_from_list) != "")
1264
1265 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1266 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1267
1268 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001269 javaVersion: javaVersion,
1270 deps: deps,
1271 checkApi: checkApi,
1272 generateStubs: generateStubs,
1273 doApiLint: doApiLint,
1274 doCheckReleased: doCheckReleased,
1275 writeSdkValues: writeSdkValues,
1276 migratingNullability: migratingNullability,
1277 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001278 }
1279 stubCmdParams.stubsType = Everything
1280 // Create default (i.e. "everything" stubs) rule for metalava
1281 d.everythingStubCmd(ctx, stubCmdParams)
1282
Jihoon Kangd40c5912024-03-05 16:12:20 +00001283 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001284 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1285 // strips all flagged apis to generate the "exportable" stubs
1286 stubCmdParams.stubsType = Exportable
1287 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001288
Jihoon Kang90f70332025-01-28 19:36:27 +00001289 if String(d.properties.Check_nullability_warnings) != "" {
1290 if d.everythingArtifacts.nullabilityWarningsFile == nil {
1291 ctx.PropertyErrorf("check_nullability_warnings",
1292 "Cannot specify check_nullability_warnings unless validating nullability")
1293 }
1294
1295 checkNullabilityWarningsPath := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1296
1297 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
1298
1299 msg := fmt.Sprintf(`\n******************************\n`+
1300 `The warnings encountered during nullability annotation validation did\n`+
1301 `not match the checked in file of expected warnings. The diffs are shown\n`+
1302 `above. You have two options:\n`+
1303 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1304 ` 2. Update the file of expected warnings by running:\n`+
1305 ` cp %s %s\n`+
1306 ` and submitting the updated file as part of your change.`,
1307 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarningsPath)
1308
1309 rule := android.NewRuleBuilder(pctx, ctx)
1310
1311 rule.Command().
1312 Text("(").
1313 Text("diff").Input(checkNullabilityWarningsPath).Input(d.everythingArtifacts.nullabilityWarningsFile).
1314 Text("&&").
1315 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1316 Text(") || (").
1317 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1318 Text("; exit 38").
1319 Text(")")
1320
1321 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1322 }
1323
Paul Duffine7a86642022-08-16 15:43:20 +00001324 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1325
1326 if len(d.Javadoc.properties.Out) > 0 {
1327 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1328 }
1329
1330 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1331 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1332 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1333
1334 if baselineFile.Valid() {
1335 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1336 }
1337
Jihoon Kang3c89f042023-12-19 02:40:22 +00001338 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001339
1340 rule := android.NewRuleBuilder(pctx, ctx)
1341
1342 // Diff command line.
1343 // -F matches the closest "opening" line, such as "package android {"
1344 // and " public class Intent {".
1345 diff := `diff -u -F '{ *$'`
1346
1347 rule.Command().Text("( true")
1348 rule.Command().
1349 Text(diff).
1350 Input(apiFile).Input(d.apiFile)
1351
1352 rule.Command().
1353 Text(diff).
1354 Input(removedApiFile).Input(d.removedApiFile)
1355
1356 msg := fmt.Sprintf(`\n******************************\n`+
1357 `You have tried to change the API from what has been previously approved.\n\n`+
1358 `To make these errors go away, you have two choices:\n`+
1359 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1360 ` to the new methods, etc. shown in the above diff.\n\n`+
1361 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1362 ` m %s-update-current-api\n\n`+
1363 ` To submit the revised current.txt to the main Android repository,\n`+
1364 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001365 `If your build failed due to stub validation, you can resolve the errors with\n`+
1366 `either of the two choices above and try re-building the target.\n`+
1367 `If the mismatch between the stubs and the current.txt is intended,\n`+
1368 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001369 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1370 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001371 `******************************\n`, ctx.ModuleName())
1372
Jihoon Kang90f70332025-01-28 19:36:27 +00001373 cmd := rule.Command().
Paul Duffine7a86642022-08-16 15:43:20 +00001374 Text("touch").Output(d.checkCurrentApiTimestamp).
1375 Text(") || (").
1376 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1377 Text("; exit 38").
1378 Text(")")
1379
Jihoon Kang90f70332025-01-28 19:36:27 +00001380 if d.apiLintTimestamp != nil {
1381 cmd.Validation(d.apiLintTimestamp)
1382 }
1383
1384 if d.checkLastReleasedApiTimestamp != nil {
1385 cmd.Validation(d.checkLastReleasedApiTimestamp)
1386 }
1387
1388 if d.checkNullabilityWarningsTimestamp != nil {
1389 cmd.Validation(d.checkNullabilityWarningsTimestamp)
1390 }
1391
Paul Duffine7a86642022-08-16 15:43:20 +00001392 rule.Build("metalavaCurrentApiCheck", "check current API")
1393
Jihoon Kang3c89f042023-12-19 02:40:22 +00001394 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001395
1396 // update API rule
1397 rule = android.NewRuleBuilder(pctx, ctx)
1398
1399 rule.Command().Text("( true")
1400
1401 rule.Command().
1402 Text("cp").Flag("-f").
1403 Input(d.apiFile).Flag(apiFile.String())
1404
1405 rule.Command().
1406 Text("cp").Flag("-f").
1407 Input(d.removedApiFile).Flag(removedApiFile.String())
1408
1409 msg = "failed to update public API"
1410
1411 rule.Command().
1412 Text("touch").Output(d.updateCurrentApiTimestamp).
1413 Text(") || (").
1414 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1415 Text("; exit 38").
1416 Text(")")
1417
1418 rule.Build("metalavaCurrentApiUpdate", "update current API")
1419 }
1420
Yu Liu35acd332025-01-24 23:11:22 +00001421 droidInfo := DroidStubsInfo{
Yu Liucbb50c22025-01-15 20:57:49 +00001422 CurrentApiTimestamp: d.CurrentApiTimestamp(),
Yu Liu35acd332025-01-24 23:11:22 +00001423 EverythingStubsInfo: StubsInfo{},
1424 ExportableStubsInfo: StubsInfo{},
1425 }
1426 setDroidInfo(ctx, d, &droidInfo.EverythingStubsInfo, Everything)
1427 setDroidInfo(ctx, d, &droidInfo.ExportableStubsInfo, Exportable)
1428 android.SetProvider(ctx, DroidStubsInfoProvider, droidInfo)
1429
1430 android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{
1431 EverythingStubsSrcJar: d.stubsSrcJar,
1432 ExportableStubsSrcJar: d.exportableStubsSrcJar,
Yu Liucbb50c22025-01-15 20:57:49 +00001433 })
1434
mrziwang39e68ff2024-07-01 16:35:32 -07001435 d.setOutputFiles(ctx)
Jihoon Kange9eecc72025-01-28 18:57:18 +00001436
1437 d.setPhonyRules(ctx)
Cole Fausta43fb252025-02-11 17:02:53 -08001438
1439 if d.apiLintTimestamp != nil {
1440 if d.apiLintReport != nil {
1441 ctx.DistForGoalsWithFilename(
1442 []string{fmt.Sprintf("%s-api-lint", d.Name()), "droidcore"},
1443 d.apiLintReport,
1444 fmt.Sprintf("apilint/%s-lint-report.txt", d.Name()),
1445 )
1446 }
1447 }
mrziwang39e68ff2024-07-01 16:35:32 -07001448}
1449
Yu Liu35acd332025-01-24 23:11:22 +00001450func setDroidInfo(ctx android.ModuleContext, d *Droidstubs, info *StubsInfo, typ StubsType) {
1451 if typ == Everything {
1452 info.ApiFile = d.apiFile
1453 info.RemovedApiFile = d.removedApiFile
1454 info.AnnotationsZip = d.everythingArtifacts.annotationsZip
1455 info.ApiVersionsXml = d.everythingArtifacts.apiVersionsXml
1456 } else if typ == Exportable {
1457 info.ApiFile = d.exportableApiFile
1458 info.RemovedApiFile = d.exportableRemovedApiFile
1459 info.AnnotationsZip = d.exportableArtifacts.annotationsZip
1460 info.ApiVersionsXml = d.exportableArtifacts.apiVersionsXml
1461 } else {
1462 ctx.ModuleErrorf("failed to set ApiVersionsXml, stubs type not supported: %d", typ)
1463 }
1464}
1465
mrziwang39e68ff2024-07-01 16:35:32 -07001466// This method sets the outputFiles property, which is used to set the
1467// OutputFilesProvider later.
1468// Droidstubs' tag supports specifying with the stubs type.
1469// While supporting the pre-existing tags, it also supports tags with
1470// the stubs type prefix. Some examples are shown below:
1471// {.annotations.zip} - pre-existing behavior. Returns the path to the
1472// annotation zip.
1473// {.exportable} - Returns the path to the exportable stubs src jar.
1474// {.exportable.annotations.zip} - Returns the path to the exportable
1475// annotations zip file.
1476// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
1477// xml file. For unsupported combinations, the default everything output file
1478// is returned.
1479func (d *Droidstubs) setOutputFiles(ctx android.ModuleContext) {
1480 tagToOutputFileFunc := map[string]func(StubsType) (android.Path, error){
1481 "": d.StubsSrcJar,
1482 ".docs.zip": d.DocZip,
1483 ".api.txt": d.ApiFilePath,
1484 android.DefaultDistTag: d.ApiFilePath,
1485 ".removed-api.txt": d.RemovedApiFilePath,
1486 ".annotations.zip": d.AnnotationsZip,
1487 ".api_versions.xml": d.ApiVersionsXmlFilePath,
1488 }
1489 stubsTypeToPrefix := map[StubsType]string{
1490 Everything: "",
1491 Exportable: ".exportable",
1492 }
1493 for _, tag := range android.SortedKeys(tagToOutputFileFunc) {
1494 for _, stubType := range android.SortedKeys(stubsTypeToPrefix) {
1495 tagWithPrefix := stubsTypeToPrefix[stubType] + tag
1496 outputFile, err := tagToOutputFileFunc[tag](stubType)
Cole Faust5146e782024-11-15 14:47:49 -08001497 if err == nil && outputFile != nil {
mrziwang39e68ff2024-07-01 16:35:32 -07001498 ctx.SetOutputFiles(android.Paths{outputFile}, tagWithPrefix)
1499 }
1500 }
1501 }
Colin Cross2207f872021-03-24 12:39:08 -07001502}
1503
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001504func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1505 api_file := d.properties.Check_api.Current.Api_file
1506 api_surface := d.properties.Api_surface
1507
1508 props := struct {
1509 Name *string
1510 Api_surface *string
1511 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001512 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001513 }{}
1514
1515 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1516 props.Api_surface = api_surface
1517 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001518 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001519
1520 ctx.CreateModule(ApiContributionFactory, &props)
1521}
1522
Spandan Das0b555e32022-11-28 18:48:51 +00001523// TODO (b/262014796): Export the API contributions of CorePlatformApi
1524// A map to populate the api surface of a droidstub from a substring appearing in its name
1525// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1526// use a strict naming convention
1527var (
1528 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
Paul Duffin2ced2eb2024-05-01 13:13:51 +01001529 // public is commented out since the core libraries use public in their java_sdk_library names
Spandan Das0b555e32022-11-28 18:48:51 +00001530 "intracore": android.SdkIntraCore,
1531 "intra.core": android.SdkIntraCore,
1532 "system_server": android.SdkSystemServer,
1533 "system-server": android.SdkSystemServer,
1534 "system": android.SdkSystem,
1535 "module_lib": android.SdkModule,
1536 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001537 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001538 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001539 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001540 }
1541)
1542
Colin Cross2207f872021-03-24 12:39:08 -07001543func StubsDefaultsFactory() android.Module {
1544 module := &DocDefaults{}
1545
1546 module.AddProperties(
1547 &JavadocProperties{},
1548 &DroidstubsProperties{},
1549 )
1550
1551 android.InitDefaultsModule(module)
1552
1553 return module
1554}
1555
1556var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1557
1558type PrebuiltStubsSourcesProperties struct {
1559 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001560
1561 // Name of the source soong module that gets shadowed by this prebuilt
1562 // If unspecified, follows the naming convention that the source module of
1563 // the prebuilt is Name() without "prebuilt_" prefix
1564 Source_module_name *string
1565
1566 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1567 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1568 // (without any prebuilt_ prefix)
1569 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1570}
1571
1572func (j *PrebuiltStubsSources) BaseModuleName() string {
1573 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1574}
1575
1576func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1577 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001578}
1579
1580type PrebuiltStubsSources struct {
1581 android.ModuleBase
1582 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001583 embeddableInModuleAndImport
1584
Colin Cross2207f872021-03-24 12:39:08 -07001585 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001586
1587 properties PrebuiltStubsSourcesProperties
1588
kgui67007242022-01-25 13:50:25 +08001589 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001590}
1591
Jihoon Kangee113282024-01-23 00:16:41 +00001592func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1593 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001594}
1595
1596func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001597 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001598 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 -07001599 return
1600 }
1601
Anton Hansson86758ac2021-11-03 14:44:12 +00001602 src := p.properties.Srcs[0]
1603 if filepath.Ext(src) == ".srcjar" {
1604 // This is a srcjar. We can use it directly.
1605 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1606 } else {
1607 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001608
Anton Hansson86758ac2021-11-03 14:44:12 +00001609 // This is a directory. Glob the contents just in case the directory does not exist.
1610 srcGlob := src + "/**/*"
1611 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001612
Anton Hansson86758ac2021-11-03 14:44:12 +00001613 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1614 // the path components are invalid it won't in this case because no components
1615 // are specified and the module directory must exist in order to get this far.
1616 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001617
Anton Hansson86758ac2021-11-03 14:44:12 +00001618 rule := android.NewRuleBuilder(pctx, ctx)
1619 rule.Command().
1620 BuiltTool("soong_zip").
1621 Flag("-write_if_changed").
1622 Flag("-jar").
1623 FlagWithOutput("-o ", outPath).
1624 FlagWithArg("-C ", srcDir.String()).
1625 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1626 rule.Restat()
1627 rule.Build("zip src", "Create srcjar from prebuilt source")
1628 p.stubsSrcJar = outPath
1629 }
mrziwangaa2a2b62024-07-01 12:09:20 -07001630
Yu Liu35acd332025-01-24 23:11:22 +00001631 android.SetProvider(ctx, StubsSrcInfoProvider, StubsSrcInfo{
1632 EverythingStubsSrcJar: p.stubsSrcJar,
1633 ExportableStubsSrcJar: p.stubsSrcJar,
1634 })
1635
mrziwangaa2a2b62024-07-01 12:09:20 -07001636 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, "")
1637 // prebuilt droidstubs does not output "exportable" stubs.
1638 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1639 ctx.SetOutputFiles(android.Paths{p.stubsSrcJar}, ".exportable")
Colin Cross2207f872021-03-24 12:39:08 -07001640}
1641
1642func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1643 return &p.prebuilt
1644}
1645
1646func (p *PrebuiltStubsSources) Name() string {
1647 return p.prebuilt.Name(p.ModuleBase.Name())
1648}
1649
1650// prebuilt_stubs_sources imports a set of java source files as if they were
1651// generated by droidstubs.
1652//
1653// By default, a prebuilt_stubs_sources has a single variant that expects a
1654// set of `.java` files generated by droidstubs.
1655//
1656// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1657// for host modules.
1658//
1659// Intended only for use by sdk snapshots.
1660func PrebuiltStubsSourcesFactory() android.Module {
1661 module := &PrebuiltStubsSources{}
1662
1663 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001664 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001665
1666 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001667 InitDroiddocModule(module, android.HostAndDeviceSupported)
1668 return module
1669}