blob: abf66406c110191c2fd5795275aad021ca6fac6d [file] [log] [blame]
Colin Cross2207f872021-03-24 12:39:08 -07001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18 "fmt"
Anton Hansson86758ac2021-11-03 14:44:12 +000019 "path/filepath"
Mårten Kongstad802ae0f2022-07-27 13:47:32 +020020 "regexp"
Colin Cross2207f872021-03-24 12:39:08 -070021 "strings"
22
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/java/config"
27 "android/soong/remoteexec"
28)
29
Pedro Loureirocc203502021-10-04 17:24:00 +000030// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070031var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000032
Jihoon Kang6592e872023-12-19 01:13:16 +000033type StubsType int
34
35const (
36 Everything StubsType = iota
37 Runtime
38 Exportable
39)
40
41func (s StubsType) String() string {
42 switch s {
43 case Everything:
44 return "everything"
45 case Runtime:
46 return "runtime"
47 case Exportable:
48 return "exportable"
49 default:
50 return ""
51 }
52}
53
Colin Cross2207f872021-03-24 12:39:08 -070054func init() {
55 RegisterStubsBuildComponents(android.InitRegistrationContext)
56}
57
58func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
59 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
60
61 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
62 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
63
64 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
65}
66
Colin Cross2207f872021-03-24 12:39:08 -070067// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070068type Droidstubs struct {
69 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000070 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070071
72 properties DroidstubsProperties
Paul Duffinc71d2b72022-08-16 15:24:01 +000073 apiFile android.Path
74 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070075 nullabilityWarningsFile android.WritablePath
76
77 checkCurrentApiTimestamp android.WritablePath
78 updateCurrentApiTimestamp android.WritablePath
79 checkLastReleasedApiTimestamp android.WritablePath
80 apiLintTimestamp android.WritablePath
81 apiLintReport android.WritablePath
82
83 checkNullabilityWarningsTimestamp android.WritablePath
84
85 annotationsZip android.WritablePath
86 apiVersionsXml android.WritablePath
87
Colin Cross2207f872021-03-24 12:39:08 -070088 metadataZip android.WritablePath
89 metadataDir android.WritablePath
Jihoon Kang3c89f042023-12-19 02:40:22 +000090
91 exportableApiFile android.WritablePath
92 exportableRemovedApiFile android.WritablePath
93 exportableNullabilityWarningsFile android.WritablePath
94 exportableAnnotationsZip android.WritablePath
95 exportableApiVersionsXml android.WritablePath
96 exportableMetadataZip android.WritablePath
97 exportableMetadataDir android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -070098}
99
100type DroidstubsProperties struct {
101 // The generated public API filename by Metalava, defaults to <module>_api.txt
102 Api_filename *string
103
104 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
105 Removed_api_filename *string
106
Colin Cross2207f872021-03-24 12:39:08 -0700107 Check_api struct {
108 Last_released ApiToCheck
109
110 Current ApiToCheck
111
112 Api_lint struct {
113 Enabled *bool
114
115 // If set, performs api_lint on any new APIs not found in the given signature file
116 New_since *string `android:"path"`
117
118 // If not blank, path to the baseline txt file for approved API lint violations.
119 Baseline_file *string `android:"path"`
120 }
121 }
122
123 // user can specify the version of previous released API file in order to do compatibility check.
124 Previous_api *string `android:"path"`
125
126 // is set to true, Metalava will allow framework SDK to contain annotations.
127 Annotations_enabled *bool
128
129 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
130 Merge_annotations_dirs []string
131
132 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
133 Merge_inclusion_annotations_dirs []string
134
135 // a file containing a list of classes to do nullability validation for.
136 Validate_nullability_from_list *string
137
138 // a file containing expected warnings produced by validation of nullability annotations.
139 Check_nullability_warnings *string
140
141 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
142 Create_doc_stubs *bool
143
144 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
145 // Has no effect if create_doc_stubs: true.
146 Output_javadoc_comments *bool
147
148 // if set to false then do not write out stubs. Defaults to true.
149 //
150 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
151 Generate_stubs *bool
152
153 // 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 -0400154 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700155 High_mem *bool
156
satayev783195c2021-06-23 21:49:57 +0100157 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700158 Api_levels_annotations_enabled *bool
159
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000160 // Apply the api levels database created by this module rather than generating one in this droidstubs.
161 Api_levels_module *string
162
Colin Cross2207f872021-03-24 12:39:08 -0700163 // the dirs which Metalava extracts API levels annotations from.
164 Api_levels_annotations_dirs []string
165
Cole Faust051fa912022-10-05 12:45:42 -0700166 // 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 +0100167 Api_levels_sdk_type *string
168
Colin Cross2207f872021-03-24 12:39:08 -0700169 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
170 Api_levels_jar_filename *string
171
172 // if set to true, collect the values used by the Dev tools and
173 // write them in files packaged with the SDK. Defaults to false.
174 Write_sdk_values *bool
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200175
176 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
177 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
178 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000179
180 // API surface of this module. If set, the module contributes to an API surface.
181 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
182 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000183
184 // a list of aconfig_declarations module names that the stubs generated in this module
185 // depend on.
186 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700187}
188
Anton Hansson52609322021-05-05 10:36:05 +0100189// Used by xsd_config
190type ApiFilePath interface {
191 ApiFilePath() android.Path
192}
193
194type ApiStubsSrcProvider interface {
195 StubsSrcJar() android.Path
196}
197
198// Provider of information about API stubs, used by java_sdk_library.
199type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100200 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100201 ApiFilePath
202 RemovedApiFilePath() android.Path
203
204 ApiStubsSrcProvider
205}
206
Jihoon Kang063ec002023-06-28 01:16:23 +0000207type currentApiTimestampProvider interface {
208 CurrentApiTimestamp() android.Path
209}
210
Jihoon Kang3c89f042023-12-19 02:40:22 +0000211type annotationFlagsParams struct {
212 migratingNullability bool
213 validatingNullability bool
214 nullabilityWarningsFile android.WritablePath
215 annotationsZip android.WritablePath
216}
217type stubsCommandParams struct {
218 srcJarDir android.ModuleOutPath
219 stubsDir android.OptionalPath
220 stubsSrcJar android.WritablePath
221 metadataZip android.WritablePath
222 metadataDir android.WritablePath
223 apiVersionsXml android.WritablePath
224 nullabilityWarningsFile android.WritablePath
225 annotationsZip android.WritablePath
226 stubConfig stubsCommandConfigParams
227}
228type stubsCommandConfigParams struct {
229 stubsType StubsType
230 javaVersion javaVersion
231 deps deps
232 checkApi bool
233 generateStubs bool
234 doApiLint bool
235 doCheckReleased bool
236 writeSdkValues bool
237 migratingNullability bool
238 validatingNullability bool
239}
240
Colin Cross2207f872021-03-24 12:39:08 -0700241// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
242// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
243// a droiddoc module to generate documentation.
244func DroidstubsFactory() android.Module {
245 module := &Droidstubs{}
246
247 module.AddProperties(&module.properties,
248 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000249 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700250
251 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000252
253 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
254 module.createApiContribution(ctx)
255 })
Colin Cross2207f872021-03-24 12:39:08 -0700256 return module
257}
258
259// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
260// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
261// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
262// module when symbols needed by the source files are provided by java_library_host modules.
263func DroidstubsHostFactory() android.Module {
264 module := &Droidstubs{}
265
266 module.AddProperties(&module.properties,
267 &module.Javadoc.properties)
268
269 InitDroiddocModule(module, android.HostSupported)
270 return module
271}
272
273func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
274 switch tag {
275 case "":
276 return android.Paths{d.stubsSrcJar}, nil
277 case ".docs.zip":
278 return android.Paths{d.docZip}, nil
279 case ".api.txt", android.DefaultDistTag:
280 // This is the default dist path for dist properties that have no tag property.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000281 return android.Paths{d.apiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700282 case ".removed-api.txt":
Paul Duffinc71d2b72022-08-16 15:24:01 +0000283 return android.Paths{d.removedApiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700284 case ".annotations.zip":
285 return android.Paths{d.annotationsZip}, nil
286 case ".api_versions.xml":
287 return android.Paths{d.apiVersionsXml}, nil
288 default:
289 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
290 }
291}
292
Anton Hanssond78eb762021-09-21 15:25:12 +0100293func (d *Droidstubs) AnnotationsZip() android.Path {
294 return d.annotationsZip
295}
296
Colin Cross2207f872021-03-24 12:39:08 -0700297func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000298 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700299}
300
301func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000302 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700303}
304
305func (d *Droidstubs) StubsSrcJar() android.Path {
306 return d.stubsSrcJar
307}
308
Jihoon Kang063ec002023-06-28 01:16:23 +0000309func (d *Droidstubs) CurrentApiTimestamp() android.Path {
310 return d.checkCurrentApiTimestamp
311}
312
Colin Cross2207f872021-03-24 12:39:08 -0700313var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
314var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
315var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000316var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000317var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700318
319func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
320 d.Javadoc.addDeps(ctx)
321
322 if len(d.properties.Merge_annotations_dirs) != 0 {
323 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
324 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
325 }
326 }
327
328 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
329 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
330 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
331 }
332 }
333
334 if len(d.properties.Api_levels_annotations_dirs) != 0 {
335 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
336 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
337 }
338 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000339
Jihoon Kang6592e872023-12-19 01:13:16 +0000340 if len(d.properties.Aconfig_declarations) != 0 {
341 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
342 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
343 }
344 }
345
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000346 if d.properties.Api_levels_module != nil {
347 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
348 }
Colin Cross2207f872021-03-24 12:39:08 -0700349}
350
Jihoon Kang3c89f042023-12-19 02:40:22 +0000351func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
352 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
353}
354
355func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
356 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700357 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000358 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000359 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000360
361 if stubsType == Everything {
362 d.apiFile = uncheckedApiFile
363 } else if stubsType == Exportable {
364 d.exportableApiFile = uncheckedApiFile
365 }
Colin Cross2207f872021-03-24 12:39:08 -0700366 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
367 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000368 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700369 }
370
Jihoon Kang3c89f042023-12-19 02:40:22 +0000371 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700372 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000373 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000374 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000375
376 if stubsType == Everything {
377 d.removedApiFile = uncheckedRemovedFile
378 } else if stubsType == Exportable {
379 d.exportableRemovedApiFile = uncheckedRemovedFile
380 }
Colin Cross2207f872021-03-24 12:39:08 -0700381 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
382 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000383 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700384 }
385
Colin Cross2207f872021-03-24 12:39:08 -0700386 if stubsDir.Valid() {
387 if Bool(d.properties.Create_doc_stubs) {
388 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
389 } else {
390 cmd.FlagWithArg("--stubs ", stubsDir.String())
391 if !Bool(d.properties.Output_javadoc_comments) {
392 cmd.Flag("--exclude-documentation-from-stubs")
393 }
394 }
395 }
396}
397
Jihoon Kang3c89f042023-12-19 02:40:22 +0000398func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Colin Cross2207f872021-03-24 12:39:08 -0700399 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400400 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100401
Jihoon Kang3c89f042023-12-19 02:40:22 +0000402 if params.migratingNullability {
Colin Cross2207f872021-03-24 12:39:08 -0700403 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
404 cmd.FlagWithInput("--migrate-nullness ", previousApi)
405 }
406
407 if s := String(d.properties.Validate_nullability_from_list); s != "" {
408 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
409 }
410
Jihoon Kang3c89f042023-12-19 02:40:22 +0000411 if params.validatingNullability {
412 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
Colin Cross2207f872021-03-24 12:39:08 -0700413 }
414
Jihoon Kang3c89f042023-12-19 02:40:22 +0000415 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Colin Cross2207f872021-03-24 12:39:08 -0700416
417 if len(d.properties.Merge_annotations_dirs) != 0 {
418 d.mergeAnnoDirFlags(ctx, cmd)
419 }
420
Liz Kammere09e20e2023-10-16 15:07:54 -0400421 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700422 }
423}
424
425func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
426 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
427 if t, ok := m.(*ExportedDroiddocDir); ok {
428 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
429 } else {
430 ctx.PropertyErrorf("merge_annotations_dirs",
431 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
432 }
433 })
434}
435
436func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
437 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
438 if t, ok := m.(*ExportedDroiddocDir); ok {
439 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
440 } else {
441 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
442 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
443 }
444 })
445}
446
Jihoon Kang3c89f042023-12-19 02:40:22 +0000447func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000448 var apiVersions android.Path
449 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000450 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000451 apiVersions = d.apiVersionsXml
452 } else {
453 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
454 if s, ok := m.(*Droidstubs); ok {
455 apiVersions = s.apiVersionsXml
456 } else {
457 ctx.PropertyErrorf("api_levels_module",
458 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
459 }
460 })
Colin Cross2207f872021-03-24 12:39:08 -0700461 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000462 if apiVersions != nil {
463 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
464 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
465 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
466 }
467}
Colin Cross2207f872021-03-24 12:39:08 -0700468
Jihoon Kang3c89f042023-12-19 02:40:22 +0000469func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700470 if len(d.properties.Api_levels_annotations_dirs) == 0 {
471 ctx.PropertyErrorf("api_levels_annotations_dirs",
472 "has to be non-empty if api levels annotations was enabled!")
473 }
474
Jihoon Kang3c89f042023-12-19 02:40:22 +0000475 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700476
477 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
478
satayev783195c2021-06-23 21:49:57 +0100479 var dirs []string
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200480 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700481 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
482 if t, ok := m.(*ExportedDroiddocDir); ok {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200483 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
484
485 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
486 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700487 for _, dep := range t.deps {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200488 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
489 if extensions_dir == "" {
490 extensions_dir = t.dir.String() + "/extensions"
491 }
492 cmd.Implicit(dep)
493 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700494 if dep.Base() == filename {
495 cmd.Implicit(dep)
496 }
497 if filename != "android.jar" && dep.Base() == "android.jar" {
498 // Metalava implicitly searches these patterns:
499 // prebuilts/tools/common/api-versions/android-%/android.jar
500 // prebuilts/sdk/%/public/android.jar
501 // Add android.jar files from the api_levels_annotations_dirs directories to try
502 // to satisfy these patterns. If Metalava can't find a match for an API level
503 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700504 cmd.Implicit(dep)
505 }
506 }
satayev783195c2021-06-23 21:49:57 +0100507
508 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700509 } else {
510 ctx.PropertyErrorf("api_levels_annotations_dirs",
511 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
512 }
513 })
satayev783195c2021-06-23 21:49:57 +0100514
515 // Add all relevant --android-jar-pattern patterns for Metalava.
516 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
517 // an actual file present on disk (in the order the patterns were passed). For system APIs for
518 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000519 // for older releases. Similarly, module-lib falls back to system API.
520 var sdkDirs []string
521 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700522 case "system-server":
523 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000524 case "module-lib":
525 sdkDirs = []string{"module-lib", "system", "public"}
526 case "system":
527 sdkDirs = []string{"system", "public"}
528 case "public":
529 sdkDirs = []string{"public"}
530 default:
531 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
532 return
satayev783195c2021-06-23 21:49:57 +0100533 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000534
535 for _, sdkDir := range sdkDirs {
536 for _, dir := range dirs {
537 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
538 }
satayev783195c2021-06-23 21:49:57 +0100539 }
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200540
541 if d.properties.Extensions_info_file != nil {
542 if extensions_dir == "" {
543 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
544 }
545 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
546 cmd.Implicit(info_file)
547 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
548 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
549 }
Colin Cross2207f872021-03-24 12:39:08 -0700550}
551
Colin Crosse52c2ac2022-03-28 17:03:35 -0700552func metalavaUseRbe(ctx android.ModuleContext) bool {
553 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
554}
555
Colin Cross2207f872021-03-24 12:39:08 -0700556func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100557 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700558 rule.Command().Text("rm -rf").Flag(homeDir.String())
559 rule.Command().Text("mkdir -p").Flag(homeDir.String())
560
Anton Hansson556e8142021-06-04 16:20:25 +0100561 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700562 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
563
Colin Crosse52c2ac2022-03-28 17:03:35 -0700564 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700565 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700566 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000567 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
568 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700569 labels := map[string]string{"type": "tool", "name": "metalava"}
570 // TODO: metalava pool rejects these jobs
571 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
572 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000573 Labels: labels,
574 ExecStrategy: execStrategy,
575 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
576 Platform: map[string]string{remoteexec.PoolKey: pool},
577 Compare: compare,
578 NumLocalRuns: 1,
579 NumRemoteRuns: 1,
580 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700581 })
Colin Cross2207f872021-03-24 12:39:08 -0700582 }
583
Colin Cross6aa5c402021-03-24 12:28:50 -0700584 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700585 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400586 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100587 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700588 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
589 FlagWithInput("@", srcJarList)
590
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100591 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
592 // years, so it is unlikely to change any time soon.
593 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
594 combinedPaths = append(combinedPaths, classpath.Paths()...)
595 if len(combinedPaths) > 0 {
596 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700597 }
598
Liz Kammere09e20e2023-10-16 15:07:54 -0400599 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000600 if ctx.DeviceConfig().HideFlaggedApis() {
Liz Kammere09e20e2023-10-16 15:07:54 -0400601 cmd.Flag(config.MetalavaHideFlaggedApis)
Jihoon Kangc8313892023-09-20 00:54:47 +0000602 }
603
Colin Cross2207f872021-03-24 12:39:08 -0700604 return cmd
605}
606
Jihoon Kang3c89f042023-12-19 02:40:22 +0000607// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
608// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
609// property is defined, apply transformations and only revert the flagged apis that are not
610// enabled via release configurations and are not specified in aconfig_declarations
611func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
612
613 if len(aconfigFlagsPaths) == 0 {
614 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
615 return
616 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000617
618 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
619 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
620
621 var filterArgs string
622 switch stubsType {
623 // No flagged apis specific flags need to be passed to metalava when generating
624 // everything stubs
625 case Everything:
626 return
627
628 case Runtime:
629 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
630
631 case Exportable:
632 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
633
634 }
635
636 ctx.Build(pctx, android.BuildParams{
637 Rule: gatherReleasedFlaggedApisRule,
638 Inputs: aconfigFlagsPaths,
639 Output: releasedFlaggedApisFile,
640 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
641 Args: map[string]string{
642 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
643 "filter_args": filterArgs,
644 },
645 })
646
647 ctx.Build(pctx, android.BuildParams{
648 Rule: generateMetalavaRevertAnnotationsRule,
649 Input: releasedFlaggedApisFile,
650 Output: revertAnnotationsFile,
651 Description: fmt.Sprintf("%s revert annotations", stubsType),
652 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000653
654 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000655}
656
Jihoon Kang3c89f042023-12-19 02:40:22 +0000657func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
658 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700659 if BoolDefault(d.properties.High_mem, false) {
660 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
661 rule.HighMem()
662 }
663
Jihoon Kang3c89f042023-12-19 02:40:22 +0000664 if params.stubConfig.generateStubs {
665 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
666 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700667 }
668
Jihoon Kang3c89f042023-12-19 02:40:22 +0000669 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700670
Jihoon Kang3c89f042023-12-19 02:40:22 +0000671 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
672 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
673 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700674 cmd.Implicits(d.Javadoc.implicits)
675
Jihoon Kang3c89f042023-12-19 02:40:22 +0000676 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700677
Jihoon Kang3c89f042023-12-19 02:40:22 +0000678 if params.stubConfig.writeSdkValues {
679 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
680 }
681
682 annotationParams := annotationFlagsParams{
683 migratingNullability: params.stubConfig.migratingNullability,
684 validatingNullability: params.stubConfig.validatingNullability,
685 nullabilityWarningsFile: params.nullabilityWarningsFile,
686 annotationsZip: params.annotationsZip,
687 }
688
689 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700690 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000691 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700692
Colin Crossbc139922021-03-25 18:33:16 -0700693 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700694
Colin Cross2207f872021-03-24 12:39:08 -0700695 for _, o := range d.Javadoc.properties.Out {
696 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
697 }
698
Jihoon Kang3c89f042023-12-19 02:40:22 +0000699 return cmd
700}
Colin Cross2207f872021-03-24 12:39:08 -0700701
Jihoon Kang3c89f042023-12-19 02:40:22 +0000702// Sandbox rule for generating the everything stubs and other artifacts
703func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
704 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
705 rule := android.NewRuleBuilder(pctx, ctx)
706 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
707 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
708 SandboxInputs()
709
710 var stubsDir android.OptionalPath
711 if params.generateStubs {
712 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
713 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
714 }
715
716 if params.writeSdkValues {
717 d.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
718 d.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
719 }
720
721 if Bool(d.properties.Annotations_enabled) {
722 if params.validatingNullability {
723 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
724 }
725 d.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
726 }
727 if Bool(d.properties.Api_levels_annotations_enabled) {
728 d.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
729 }
730
731 commonCmdParams := stubsCommandParams{
732 srcJarDir: srcJarDir,
733 stubsDir: stubsDir,
734 stubsSrcJar: d.Javadoc.stubsSrcJar,
735 metadataDir: d.metadataDir,
736 apiVersionsXml: d.apiVersionsXml,
737 nullabilityWarningsFile: d.nullabilityWarningsFile,
738 annotationsZip: d.annotationsZip,
739 stubConfig: params,
740 }
741
742 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
743
744 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
745
746 if params.generateStubs {
747 rule.Command().
748 BuiltTool("soong_zip").
749 Flag("-write_if_changed").
750 Flag("-jar").
751 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
752 FlagWithArg("-C ", stubsDir.String()).
753 FlagWithArg("-D ", stubsDir.String())
754 }
755
756 if params.writeSdkValues {
757 rule.Command().
758 BuiltTool("soong_zip").
759 Flag("-write_if_changed").
760 Flag("-d").
761 FlagWithOutput("-o ", d.metadataZip).
762 FlagWithArg("-C ", d.metadataDir.String()).
763 FlagWithArg("-D ", d.metadataDir.String())
764 }
765
766 // TODO: We don't really need two separate API files, but this is a reminiscence of how
767 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
768 if params.doApiLint {
769 rule.Command().Text("touch").Output(d.apiLintTimestamp)
770 }
771 if params.doCheckReleased {
772 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
773 }
774
775 // TODO(b/183630617): rewrapper doesn't support restat rules
776 if !metalavaUseRbe(ctx) {
777 rule.Restat()
778 }
779
780 zipSyncCleanupCmd(rule, srcJarDir)
781
782 rule.Build("metalava", "metalava merged")
783}
784
785// Sandbox rule for generating the everything artifacts that are not run by
786// default but only run based on the module configurations
787func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700788
789 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000790 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700791 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
792 if newSince.Valid() {
793 cmd.FlagWithInput("--api-lint ", newSince.Path())
794 } else {
795 cmd.Flag("--api-lint")
796 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000797 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700798 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
799
Colin Cross0d532412021-03-25 09:38:45 -0700800 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700801 if d.Name() != "android.car-system-stubs-docs" &&
802 d.Name() != "android.car-stubs-docs" {
803 cmd.Flag("--lints-as-errors")
804 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
805 }
806
807 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000808 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
809 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700810
811 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700812 //
813 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
814 // message and metalava's one?
815 msg := `$'` + // Enclose with $' ... '
816 `************************************************************\n` +
817 `Your API changes are triggering API Lint warnings or errors.\n` +
818 `To make these errors go away, fix the code according to the\n` +
819 `error and/or warning messages above.\n` +
820 `\n` +
821 `If it is not possible to do so, there are workarounds:\n` +
822 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000823 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
824 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700825
826 if baselineFile.Valid() {
827 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
828 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
829
830 msg += fmt.Sprintf(``+
831 `2. You can update the baseline by executing the following\n`+
832 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700833 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
834 ` "%s" \\\n`+
835 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700836 ` To submit the revised baseline.txt to the main Android\n`+
837 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
838 } else {
839 msg += fmt.Sprintf(``+
840 `2. You can add a baseline file of existing lint failures\n`+
841 ` to the build rule of %s.\n`, d.Name())
842 }
843 // Note the message ends with a ' (single quote), to close the $' ... ' .
844 msg += `************************************************************\n'`
845
846 cmd.FlagWithArg("--error-message:api-lint ", msg)
847 }
848
849 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000850 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700851 if len(d.Javadoc.properties.Out) > 0 {
852 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
853 }
854
855 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
856 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
857 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000858 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700859
Jihoon Kang3c89f042023-12-19 02:40:22 +0000860 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700861
862 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
863 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
864
865 if baselineFile.Valid() {
866 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
867 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
868 }
869
870 // Note this string includes quote ($' ... '), which decodes the "\n"s.
871 msg := `$'\n******************************\n` +
872 `You have tried to change the API from what has been previously released in\n` +
873 `an SDK. Please fix the errors listed above.\n` +
874 `******************************\n'`
875
876 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
877 }
878
Paul Duffin10a23c22023-08-11 22:47:31 +0100879 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
880 // Pass the current API file into metalava so it can use it as the basis for determining how to
881 // generate the output signature files (both api and removed).
882 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
883 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
884 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000885}
Paul Duffin10a23c22023-08-11 22:47:31 +0100886
Jihoon Kang3c89f042023-12-19 02:40:22 +0000887// Sandbox rule for generating exportable stubs and other artifacts
888func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
889 optionalCmdParams := stubsCommandParams{
890 stubConfig: params,
891 }
892
893 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
894 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
895 if params.writeSdkValues {
896 d.exportableMetadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
897 d.exportableMetadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
898 optionalCmdParams.metadataZip = d.exportableMetadataZip
899 optionalCmdParams.metadataDir = d.exportableMetadataDir
900 }
901
902 if Bool(d.properties.Annotations_enabled) {
903 if params.validatingNullability {
904 d.exportableNullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
905 optionalCmdParams.nullabilityWarningsFile = d.exportableNullabilityWarningsFile
906 }
907 d.exportableAnnotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
908 optionalCmdParams.annotationsZip = d.exportableAnnotationsZip
909 }
910 if Bool(d.properties.Api_levels_annotations_enabled) {
911 d.exportableApiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
912 optionalCmdParams.apiVersionsXml = d.exportableApiVersionsXml
913 }
914
915 if params.checkApi || String(d.properties.Api_filename) != "" {
916 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
917 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
918 }
919
920 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
921 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
922 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
923 }
924
925 d.optionalStubCmd(ctx, optionalCmdParams)
926}
927
928func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
929
930 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
931 rule := android.NewRuleBuilder(pctx, ctx)
932 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
933 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
934 SandboxInputs()
935
936 if params.stubConfig.generateStubs {
937 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
938 }
939
940 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
941
942 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
943
944 if params.stubConfig.doApiLint {
945 // Pass the lint baseline file as an input to resolve the lint errors.
946 // The exportable stubs generation does not update the lint baseline file.
947 // Lint baseline file update is handled by the everything stubs
948 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
949 if baselineFile.Valid() {
950 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
951 }
952 }
953
954 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -0700955 rule.Command().
956 BuiltTool("soong_zip").
957 Flag("-write_if_changed").
958 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +0000959 FlagWithOutput("-o ", params.stubsSrcJar).
960 FlagWithArg("-C ", params.stubsDir.String()).
961 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700962 }
963
Jihoon Kang3c89f042023-12-19 02:40:22 +0000964 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -0700965 rule.Command().
966 BuiltTool("soong_zip").
967 Flag("-write_if_changed").
968 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +0000969 FlagWithOutput("-o ", params.metadataZip).
970 FlagWithArg("-C ", params.metadataDir.String()).
971 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700972 }
973
Colin Cross6aa5c402021-03-24 12:28:50 -0700974 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -0700975 if !metalavaUseRbe(ctx) {
976 rule.Restat()
977 }
Colin Cross2207f872021-03-24 12:39:08 -0700978
Jihoon Kang3c89f042023-12-19 02:40:22 +0000979 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -0700980
Jihoon Kang3c89f042023-12-19 02:40:22 +0000981 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
982}
983
984func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
985 deps := d.Javadoc.collectDeps(ctx)
986
987 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
988 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
989
990 // Add options for the other optional tasks: API-lint and check-released.
991 // We generate separate timestamp files for them.
992 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
993 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
994
995 writeSdkValues := Bool(d.properties.Write_sdk_values)
996
997 annotationsEnabled := Bool(d.properties.Annotations_enabled)
998
999 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1000 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1001 String(d.properties.Validate_nullability_from_list) != "")
1002
1003 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1004 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1005
1006 stubCmdParams := stubsCommandConfigParams{
1007 javaVersion: javaVersion,
1008 deps: deps,
1009 checkApi: checkApi,
1010 generateStubs: generateStubs,
1011 doApiLint: doApiLint,
1012 doCheckReleased: doCheckReleased,
1013 writeSdkValues: writeSdkValues,
1014 migratingNullability: migratingNullability,
1015 validatingNullability: validatingNullability,
1016 }
1017 stubCmdParams.stubsType = Everything
1018 // Create default (i.e. "everything" stubs) rule for metalava
1019 d.everythingStubCmd(ctx, stubCmdParams)
1020
1021 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
1022 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1023 // strips all flagged apis to generate the "exportable" stubs
1024 stubCmdParams.stubsType = Exportable
1025 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001026
Paul Duffine7a86642022-08-16 15:43:20 +00001027 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1028
1029 if len(d.Javadoc.properties.Out) > 0 {
1030 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1031 }
1032
1033 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1034 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1035 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1036
1037 if baselineFile.Valid() {
1038 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1039 }
1040
Jihoon Kang3c89f042023-12-19 02:40:22 +00001041 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001042
1043 rule := android.NewRuleBuilder(pctx, ctx)
1044
1045 // Diff command line.
1046 // -F matches the closest "opening" line, such as "package android {"
1047 // and " public class Intent {".
1048 diff := `diff -u -F '{ *$'`
1049
1050 rule.Command().Text("( true")
1051 rule.Command().
1052 Text(diff).
1053 Input(apiFile).Input(d.apiFile)
1054
1055 rule.Command().
1056 Text(diff).
1057 Input(removedApiFile).Input(d.removedApiFile)
1058
1059 msg := fmt.Sprintf(`\n******************************\n`+
1060 `You have tried to change the API from what has been previously approved.\n\n`+
1061 `To make these errors go away, you have two choices:\n`+
1062 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1063 ` to the new methods, etc. shown in the above diff.\n\n`+
1064 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1065 ` m %s-update-current-api\n\n`+
1066 ` To submit the revised current.txt to the main Android repository,\n`+
1067 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001068 `If your build failed due to stub validation, you can resolve the errors with\n`+
1069 `either of the two choices above and try re-building the target.\n`+
1070 `If the mismatch between the stubs and the current.txt is intended,\n`+
1071 `you can try re-building the target by executing the following command:\n`+
1072 `m DISABLE_STUB_VALIDATION=true <your build target>\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001073 `******************************\n`, ctx.ModuleName())
1074
1075 rule.Command().
1076 Text("touch").Output(d.checkCurrentApiTimestamp).
1077 Text(") || (").
1078 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1079 Text("; exit 38").
1080 Text(")")
1081
1082 rule.Build("metalavaCurrentApiCheck", "check current API")
1083
Jihoon Kang3c89f042023-12-19 02:40:22 +00001084 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001085
1086 // update API rule
1087 rule = android.NewRuleBuilder(pctx, ctx)
1088
1089 rule.Command().Text("( true")
1090
1091 rule.Command().
1092 Text("cp").Flag("-f").
1093 Input(d.apiFile).Flag(apiFile.String())
1094
1095 rule.Command().
1096 Text("cp").Flag("-f").
1097 Input(d.removedApiFile).Flag(removedApiFile.String())
1098
1099 msg = "failed to update public API"
1100
1101 rule.Command().
1102 Text("touch").Output(d.updateCurrentApiTimestamp).
1103 Text(") || (").
1104 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1105 Text("; exit 38").
1106 Text(")")
1107
1108 rule.Build("metalavaCurrentApiUpdate", "update current API")
1109 }
1110
Colin Cross2207f872021-03-24 12:39:08 -07001111 if String(d.properties.Check_nullability_warnings) != "" {
1112 if d.nullabilityWarningsFile == nil {
1113 ctx.PropertyErrorf("check_nullability_warnings",
1114 "Cannot specify check_nullability_warnings unless validating nullability")
1115 }
1116
1117 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1118
Jihoon Kang3c89f042023-12-19 02:40:22 +00001119 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001120
1121 msg := fmt.Sprintf(`\n******************************\n`+
1122 `The warnings encountered during nullability annotation validation did\n`+
1123 `not match the checked in file of expected warnings. The diffs are shown\n`+
1124 `above. You have two options:\n`+
1125 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1126 ` 2. Update the file of expected warnings by running:\n`+
1127 ` cp %s %s\n`+
1128 ` and submitting the updated file as part of your change.`,
1129 d.nullabilityWarningsFile, checkNullabilityWarnings)
1130
1131 rule := android.NewRuleBuilder(pctx, ctx)
1132
1133 rule.Command().
1134 Text("(").
1135 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
1136 Text("&&").
1137 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1138 Text(") || (").
1139 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1140 Text("; exit 38").
1141 Text(")")
1142
1143 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1144 }
1145}
1146
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001147func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1148 api_file := d.properties.Check_api.Current.Api_file
1149 api_surface := d.properties.Api_surface
1150
1151 props := struct {
1152 Name *string
1153 Api_surface *string
1154 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001155 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001156 }{}
1157
1158 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1159 props.Api_surface = api_surface
1160 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001161 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001162
1163 ctx.CreateModule(ApiContributionFactory, &props)
1164}
1165
Spandan Das0b555e32022-11-28 18:48:51 +00001166// TODO (b/262014796): Export the API contributions of CorePlatformApi
1167// A map to populate the api surface of a droidstub from a substring appearing in its name
1168// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1169// use a strict naming convention
1170var (
1171 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1172 //public is commented out since the core libraries use public in their java_sdk_library names
1173 "intracore": android.SdkIntraCore,
1174 "intra.core": android.SdkIntraCore,
1175 "system_server": android.SdkSystemServer,
1176 "system-server": android.SdkSystemServer,
1177 "system": android.SdkSystem,
1178 "module_lib": android.SdkModule,
1179 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001180 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001181 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001182 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001183 }
1184)
1185
Colin Cross2207f872021-03-24 12:39:08 -07001186func StubsDefaultsFactory() android.Module {
1187 module := &DocDefaults{}
1188
1189 module.AddProperties(
1190 &JavadocProperties{},
1191 &DroidstubsProperties{},
1192 )
1193
1194 android.InitDefaultsModule(module)
1195
1196 return module
1197}
1198
1199var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1200
1201type PrebuiltStubsSourcesProperties struct {
1202 Srcs []string `android:"path"`
1203}
1204
1205type PrebuiltStubsSources struct {
1206 android.ModuleBase
1207 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001208 embeddableInModuleAndImport
1209
Colin Cross2207f872021-03-24 12:39:08 -07001210 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001211
1212 properties PrebuiltStubsSourcesProperties
1213
kgui67007242022-01-25 13:50:25 +08001214 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001215}
1216
1217func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1218 switch tag {
1219 case "":
1220 return android.Paths{p.stubsSrcJar}, nil
1221 default:
1222 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1223 }
1224}
1225
1226func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
1227 return d.stubsSrcJar
1228}
1229
1230func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001231 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001232 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 -07001233 return
1234 }
1235
Anton Hansson86758ac2021-11-03 14:44:12 +00001236 src := p.properties.Srcs[0]
1237 if filepath.Ext(src) == ".srcjar" {
1238 // This is a srcjar. We can use it directly.
1239 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1240 } else {
1241 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001242
Anton Hansson86758ac2021-11-03 14:44:12 +00001243 // This is a directory. Glob the contents just in case the directory does not exist.
1244 srcGlob := src + "/**/*"
1245 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001246
Anton Hansson86758ac2021-11-03 14:44:12 +00001247 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1248 // the path components are invalid it won't in this case because no components
1249 // are specified and the module directory must exist in order to get this far.
1250 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001251
Anton Hansson86758ac2021-11-03 14:44:12 +00001252 rule := android.NewRuleBuilder(pctx, ctx)
1253 rule.Command().
1254 BuiltTool("soong_zip").
1255 Flag("-write_if_changed").
1256 Flag("-jar").
1257 FlagWithOutput("-o ", outPath).
1258 FlagWithArg("-C ", srcDir.String()).
1259 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1260 rule.Restat()
1261 rule.Build("zip src", "Create srcjar from prebuilt source")
1262 p.stubsSrcJar = outPath
1263 }
Colin Cross2207f872021-03-24 12:39:08 -07001264}
1265
1266func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1267 return &p.prebuilt
1268}
1269
1270func (p *PrebuiltStubsSources) Name() string {
1271 return p.prebuilt.Name(p.ModuleBase.Name())
1272}
1273
1274// prebuilt_stubs_sources imports a set of java source files as if they were
1275// generated by droidstubs.
1276//
1277// By default, a prebuilt_stubs_sources has a single variant that expects a
1278// set of `.java` files generated by droidstubs.
1279//
1280// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1281// for host modules.
1282//
1283// Intended only for use by sdk snapshots.
1284func PrebuiltStubsSourcesFactory() android.Module {
1285 module := &PrebuiltStubsSources{}
1286
1287 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001288 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001289
1290 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001291 InitDroiddocModule(module, android.HostAndDeviceSupported)
1292 return module
1293}