blob: bdbaf9281c58a89c181396a580c94b64537bb1d2 [file] [log] [blame]
Colin Cross2207f872021-03-24 12:39:08 -07001// Copyright 2021 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package java
16
17import (
18 "fmt"
Anton Hansson86758ac2021-11-03 14:44:12 +000019 "path/filepath"
Mårten Kongstad802ae0f2022-07-27 13:47:32 +020020 "regexp"
Colin Cross2207f872021-03-24 12:39:08 -070021 "strings"
22
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/java/config"
27 "android/soong/remoteexec"
28)
29
Pedro Loureirocc203502021-10-04 17:24:00 +000030// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070031var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000032
Jihoon Kang6592e872023-12-19 01:13:16 +000033type StubsType int
34
35const (
36 Everything StubsType = iota
37 Runtime
38 Exportable
Jihoon Kang78f89142023-12-27 01:40:29 +000039 Unavailable
Jihoon Kang6592e872023-12-19 01:13:16 +000040)
41
42func (s StubsType) String() string {
43 switch s {
44 case Everything:
45 return "everything"
46 case Runtime:
47 return "runtime"
48 case Exportable:
49 return "exportable"
50 default:
51 return ""
52 }
53}
54
Colin Cross2207f872021-03-24 12:39:08 -070055func init() {
56 RegisterStubsBuildComponents(android.InitRegistrationContext)
57}
58
59func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
60 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
61
62 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
63 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
64
65 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
66}
67
Colin Cross2207f872021-03-24 12:39:08 -070068// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070069type Droidstubs struct {
70 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000071 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070072
73 properties DroidstubsProperties
Paul Duffinc71d2b72022-08-16 15:24:01 +000074 apiFile android.Path
75 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070076 nullabilityWarningsFile android.WritablePath
77
78 checkCurrentApiTimestamp android.WritablePath
79 updateCurrentApiTimestamp android.WritablePath
80 checkLastReleasedApiTimestamp android.WritablePath
81 apiLintTimestamp android.WritablePath
82 apiLintReport android.WritablePath
83
84 checkNullabilityWarningsTimestamp android.WritablePath
85
86 annotationsZip android.WritablePath
87 apiVersionsXml android.WritablePath
88
Colin Cross2207f872021-03-24 12:39:08 -070089 metadataZip android.WritablePath
90 metadataDir android.WritablePath
Jihoon Kang3c89f042023-12-19 02:40:22 +000091
92 exportableApiFile android.WritablePath
93 exportableRemovedApiFile android.WritablePath
94 exportableNullabilityWarningsFile android.WritablePath
95 exportableAnnotationsZip android.WritablePath
96 exportableApiVersionsXml android.WritablePath
97 exportableMetadataZip android.WritablePath
98 exportableMetadataDir android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -070099}
100
101type DroidstubsProperties struct {
102 // The generated public API filename by Metalava, defaults to <module>_api.txt
103 Api_filename *string
104
105 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
106 Removed_api_filename *string
107
Colin Cross2207f872021-03-24 12:39:08 -0700108 Check_api struct {
109 Last_released ApiToCheck
110
111 Current ApiToCheck
112
113 Api_lint struct {
114 Enabled *bool
115
116 // If set, performs api_lint on any new APIs not found in the given signature file
117 New_since *string `android:"path"`
118
119 // If not blank, path to the baseline txt file for approved API lint violations.
120 Baseline_file *string `android:"path"`
121 }
122 }
123
124 // user can specify the version of previous released API file in order to do compatibility check.
125 Previous_api *string `android:"path"`
126
127 // is set to true, Metalava will allow framework SDK to contain annotations.
128 Annotations_enabled *bool
129
130 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
131 Merge_annotations_dirs []string
132
133 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
134 Merge_inclusion_annotations_dirs []string
135
136 // a file containing a list of classes to do nullability validation for.
137 Validate_nullability_from_list *string
138
139 // a file containing expected warnings produced by validation of nullability annotations.
140 Check_nullability_warnings *string
141
142 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
143 Create_doc_stubs *bool
144
145 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
146 // Has no effect if create_doc_stubs: true.
147 Output_javadoc_comments *bool
148
149 // if set to false then do not write out stubs. Defaults to true.
150 //
151 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
152 Generate_stubs *bool
153
154 // 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 -0400155 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700156 High_mem *bool
157
satayev783195c2021-06-23 21:49:57 +0100158 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700159 Api_levels_annotations_enabled *bool
160
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000161 // Apply the api levels database created by this module rather than generating one in this droidstubs.
162 Api_levels_module *string
163
Colin Cross2207f872021-03-24 12:39:08 -0700164 // the dirs which Metalava extracts API levels annotations from.
165 Api_levels_annotations_dirs []string
166
Cole Faust051fa912022-10-05 12:45:42 -0700167 // 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 +0100168 Api_levels_sdk_type *string
169
Colin Cross2207f872021-03-24 12:39:08 -0700170 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
171 Api_levels_jar_filename *string
172
173 // if set to true, collect the values used by the Dev tools and
174 // write them in files packaged with the SDK. Defaults to false.
175 Write_sdk_values *bool
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200176
177 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
178 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
179 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000180
181 // API surface of this module. If set, the module contributes to an API surface.
182 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
183 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000184
185 // a list of aconfig_declarations module names that the stubs generated in this module
186 // depend on.
187 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700188}
189
Anton Hansson52609322021-05-05 10:36:05 +0100190// Used by xsd_config
191type ApiFilePath interface {
192 ApiFilePath() android.Path
193}
194
195type ApiStubsSrcProvider interface {
196 StubsSrcJar() android.Path
197}
198
199// Provider of information about API stubs, used by java_sdk_library.
200type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100201 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100202 ApiFilePath
203 RemovedApiFilePath() android.Path
204
205 ApiStubsSrcProvider
206}
207
Jihoon Kang063ec002023-06-28 01:16:23 +0000208type currentApiTimestampProvider interface {
209 CurrentApiTimestamp() android.Path
210}
211
Jihoon Kang3c89f042023-12-19 02:40:22 +0000212type annotationFlagsParams struct {
213 migratingNullability bool
214 validatingNullability bool
215 nullabilityWarningsFile android.WritablePath
216 annotationsZip android.WritablePath
217}
218type stubsCommandParams struct {
219 srcJarDir android.ModuleOutPath
220 stubsDir android.OptionalPath
221 stubsSrcJar android.WritablePath
222 metadataZip android.WritablePath
223 metadataDir android.WritablePath
224 apiVersionsXml android.WritablePath
225 nullabilityWarningsFile android.WritablePath
226 annotationsZip android.WritablePath
227 stubConfig stubsCommandConfigParams
228}
229type stubsCommandConfigParams struct {
230 stubsType StubsType
231 javaVersion javaVersion
232 deps deps
233 checkApi bool
234 generateStubs bool
235 doApiLint bool
236 doCheckReleased bool
237 writeSdkValues bool
238 migratingNullability bool
239 validatingNullability bool
240}
241
Colin Cross2207f872021-03-24 12:39:08 -0700242// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
243// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
244// a droiddoc module to generate documentation.
245func DroidstubsFactory() android.Module {
246 module := &Droidstubs{}
247
248 module.AddProperties(&module.properties,
249 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000250 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700251
252 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000253
254 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
255 module.createApiContribution(ctx)
256 })
Colin Cross2207f872021-03-24 12:39:08 -0700257 return module
258}
259
260// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
261// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
262// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
263// module when symbols needed by the source files are provided by java_library_host modules.
264func DroidstubsHostFactory() android.Module {
265 module := &Droidstubs{}
266
267 module.AddProperties(&module.properties,
268 &module.Javadoc.properties)
269
270 InitDroiddocModule(module, android.HostSupported)
271 return module
272}
273
Jihoon Kang78f89142023-12-27 01:40:29 +0000274func getStubsTypeAndTag(tag string) (StubsType, string, error) {
275 if len(tag) == 0 {
276 return Everything, "", nil
277 }
278 if tag[0] != '.' {
279 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
280 }
281
282 stubsType := Everything
283 // Check if the tag has a stubs type prefix (e.g. ".exportable")
284 for st := Everything; st <= Exportable; st++ {
285 if strings.HasPrefix(tag, "."+st.String()) {
286 stubsType = st
287 }
288 }
289
290 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
291}
292
293// Droidstubs' tag supports specifying with the stubs type.
294// While supporting the pre-existing tags, it also supports tags with
295// the stubs type prefix. Some examples are shown below:
296// {.annotations.zip} - pre-existing behavior. Returns the path to the
297// annotation zip.
298// {.exportable} - Returns the path to the exportable stubs src jar.
299// {.exportable.annotations.zip} - Returns the path to the exportable
300// annotations zip file.
301// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
302// xml file. For unsupported combinations, the default everything output file
303// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700304func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000305 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
306 if err != nil {
307 return nil, err
308 }
309 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700310 case "":
Jihoon Kang78f89142023-12-27 01:40:29 +0000311 return d.StubsSrcJarWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700312 case ".docs.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000313 return d.DocZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700314 case ".api.txt", android.DefaultDistTag:
315 // This is the default dist path for dist properties that have no tag property.
Jihoon Kang78f89142023-12-27 01:40:29 +0000316 return d.ApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700317 case ".removed-api.txt":
Jihoon Kang78f89142023-12-27 01:40:29 +0000318 return d.RemovedApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700319 case ".annotations.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000320 return d.AnnotationsZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700321 case ".api_versions.xml":
Jihoon Kang78f89142023-12-27 01:40:29 +0000322 return d.ApiVersionsXmlFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700323 default:
324 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
325 }
326}
327
Anton Hanssond78eb762021-09-21 15:25:12 +0100328func (d *Droidstubs) AnnotationsZip() android.Path {
329 return d.annotationsZip
330}
331
Jihoon Kang78f89142023-12-27 01:40:29 +0000332func (d *Droidstubs) ExportableAnnotationsZip() android.Path {
333 return d.exportableAnnotationsZip
334}
335
336func (d *Droidstubs) AnnotationsZipWithStubsType(stubsType StubsType) (android.Paths, error) {
337 switch stubsType {
338 case Everything:
339 return android.Paths{d.AnnotationsZip()}, nil
340 case Exportable:
341 return android.Paths{d.ExportableAnnotationsZip()}, nil
342 default:
343 return nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
344 }
345}
346
Colin Cross2207f872021-03-24 12:39:08 -0700347func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000348 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700349}
350
Jihoon Kang78f89142023-12-27 01:40:29 +0000351func (d *Droidstubs) ExportableApiFilePath() android.Path {
352 return d.exportableApiFile
353}
354
355func (d *Droidstubs) ApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
356 switch stubsType {
357 case Everything:
358 return android.Paths{d.ApiFilePath()}, nil
359 case Exportable:
360 return android.Paths{d.ExportableApiFilePath()}, nil
361 default:
362 return nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
363 }
364}
365
366func (d *Droidstubs) ApiVersionsXmlFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
367 switch stubsType {
368 case Everything:
369 return android.Paths{d.apiVersionsXml}, nil
370 default:
371 return nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
372 }
373}
374
375func (d *Droidstubs) DocZipWithStubsType(stubsType StubsType) (android.Paths, error) {
376 switch stubsType {
377 case Everything:
378 return android.Paths{d.docZip}, nil
379 default:
380 return nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
381 }
382}
383
Colin Cross2207f872021-03-24 12:39:08 -0700384func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000385 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700386}
387
Jihoon Kang78f89142023-12-27 01:40:29 +0000388func (d *Droidstubs) ExportableRemovedApiFilePath() android.Path {
389 return d.exportableRemovedApiFile
390}
391
392func (d *Droidstubs) RemovedApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
393 switch stubsType {
394 case Everything:
395 return android.Paths{d.RemovedApiFilePath()}, nil
396 case Exportable:
397 return android.Paths{d.ExportableRemovedApiFilePath()}, nil
398 default:
399 return nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
400 }
401}
402
Colin Cross2207f872021-03-24 12:39:08 -0700403func (d *Droidstubs) StubsSrcJar() android.Path {
404 return d.stubsSrcJar
405}
406
Jihoon Kang78f89142023-12-27 01:40:29 +0000407func (d *Droidstubs) ExportableStubsSrcJar() android.Path {
408 return d.exportableStubsSrcJar
409}
410
411func (d *Droidstubs) StubsSrcJarWithStubsType(stubsType StubsType) (android.Paths, error) {
412 switch stubsType {
413 case Everything:
414 return android.Paths{d.StubsSrcJar()}, nil
415 case Exportable:
416 return android.Paths{d.ExportableStubsSrcJar()}, nil
417 default:
418 return nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
419 }
420}
421
Jihoon Kang063ec002023-06-28 01:16:23 +0000422func (d *Droidstubs) CurrentApiTimestamp() android.Path {
423 return d.checkCurrentApiTimestamp
424}
425
Colin Cross2207f872021-03-24 12:39:08 -0700426var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
427var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
428var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000429var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000430var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700431
432func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
433 d.Javadoc.addDeps(ctx)
434
435 if len(d.properties.Merge_annotations_dirs) != 0 {
436 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
437 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
438 }
439 }
440
441 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
442 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
443 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
444 }
445 }
446
447 if len(d.properties.Api_levels_annotations_dirs) != 0 {
448 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
449 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
450 }
451 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000452
Jihoon Kang6592e872023-12-19 01:13:16 +0000453 if len(d.properties.Aconfig_declarations) != 0 {
454 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
455 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
456 }
457 }
458
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000459 if d.properties.Api_levels_module != nil {
460 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
461 }
Colin Cross2207f872021-03-24 12:39:08 -0700462}
463
Jihoon Kang3c89f042023-12-19 02:40:22 +0000464func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
465 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
466}
467
468func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
469 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700470 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000471 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000472 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000473
474 if stubsType == Everything {
475 d.apiFile = uncheckedApiFile
476 } else if stubsType == Exportable {
477 d.exportableApiFile = uncheckedApiFile
478 }
Colin Cross2207f872021-03-24 12:39:08 -0700479 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
480 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000481 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700482 }
483
Jihoon Kang3c89f042023-12-19 02:40:22 +0000484 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700485 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000486 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000487 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000488
489 if stubsType == Everything {
490 d.removedApiFile = uncheckedRemovedFile
491 } else if stubsType == Exportable {
492 d.exportableRemovedApiFile = uncheckedRemovedFile
493 }
Colin Cross2207f872021-03-24 12:39:08 -0700494 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
495 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000496 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700497 }
498
Colin Cross2207f872021-03-24 12:39:08 -0700499 if stubsDir.Valid() {
500 if Bool(d.properties.Create_doc_stubs) {
501 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
502 } else {
503 cmd.FlagWithArg("--stubs ", stubsDir.String())
504 if !Bool(d.properties.Output_javadoc_comments) {
505 cmd.Flag("--exclude-documentation-from-stubs")
506 }
507 }
508 }
509}
510
Jihoon Kang3c89f042023-12-19 02:40:22 +0000511func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Colin Cross2207f872021-03-24 12:39:08 -0700512 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400513 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100514
Jihoon Kang3c89f042023-12-19 02:40:22 +0000515 if params.migratingNullability {
Colin Cross2207f872021-03-24 12:39:08 -0700516 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
517 cmd.FlagWithInput("--migrate-nullness ", previousApi)
518 }
519
520 if s := String(d.properties.Validate_nullability_from_list); s != "" {
521 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
522 }
523
Jihoon Kang3c89f042023-12-19 02:40:22 +0000524 if params.validatingNullability {
525 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
Colin Cross2207f872021-03-24 12:39:08 -0700526 }
527
Jihoon Kang3c89f042023-12-19 02:40:22 +0000528 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Colin Cross2207f872021-03-24 12:39:08 -0700529
530 if len(d.properties.Merge_annotations_dirs) != 0 {
531 d.mergeAnnoDirFlags(ctx, cmd)
532 }
533
Liz Kammere09e20e2023-10-16 15:07:54 -0400534 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700535 }
536}
537
538func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
539 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
540 if t, ok := m.(*ExportedDroiddocDir); ok {
541 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
542 } else {
543 ctx.PropertyErrorf("merge_annotations_dirs",
544 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
545 }
546 })
547}
548
549func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
550 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
551 if t, ok := m.(*ExportedDroiddocDir); ok {
552 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
553 } else {
554 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
555 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
556 }
557 })
558}
559
Jihoon Kang3c89f042023-12-19 02:40:22 +0000560func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000561 var apiVersions android.Path
562 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000563 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000564 apiVersions = d.apiVersionsXml
565 } else {
566 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
567 if s, ok := m.(*Droidstubs); ok {
568 apiVersions = s.apiVersionsXml
569 } else {
570 ctx.PropertyErrorf("api_levels_module",
571 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
572 }
573 })
Colin Cross2207f872021-03-24 12:39:08 -0700574 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000575 if apiVersions != nil {
576 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
577 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
578 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
579 }
580}
Colin Cross2207f872021-03-24 12:39:08 -0700581
Jihoon Kang3c89f042023-12-19 02:40:22 +0000582func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700583 if len(d.properties.Api_levels_annotations_dirs) == 0 {
584 ctx.PropertyErrorf("api_levels_annotations_dirs",
585 "has to be non-empty if api levels annotations was enabled!")
586 }
587
Jihoon Kang3c89f042023-12-19 02:40:22 +0000588 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700589
590 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
591
satayev783195c2021-06-23 21:49:57 +0100592 var dirs []string
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200593 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700594 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
595 if t, ok := m.(*ExportedDroiddocDir); ok {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200596 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
597
598 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
599 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700600 for _, dep := range t.deps {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200601 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
602 if extensions_dir == "" {
603 extensions_dir = t.dir.String() + "/extensions"
604 }
605 cmd.Implicit(dep)
606 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700607 if dep.Base() == filename {
608 cmd.Implicit(dep)
609 }
610 if filename != "android.jar" && dep.Base() == "android.jar" {
611 // Metalava implicitly searches these patterns:
612 // prebuilts/tools/common/api-versions/android-%/android.jar
613 // prebuilts/sdk/%/public/android.jar
614 // Add android.jar files from the api_levels_annotations_dirs directories to try
615 // to satisfy these patterns. If Metalava can't find a match for an API level
616 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700617 cmd.Implicit(dep)
618 }
619 }
satayev783195c2021-06-23 21:49:57 +0100620
621 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700622 } else {
623 ctx.PropertyErrorf("api_levels_annotations_dirs",
624 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
625 }
626 })
satayev783195c2021-06-23 21:49:57 +0100627
628 // Add all relevant --android-jar-pattern patterns for Metalava.
629 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
630 // an actual file present on disk (in the order the patterns were passed). For system APIs for
631 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000632 // for older releases. Similarly, module-lib falls back to system API.
633 var sdkDirs []string
634 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700635 case "system-server":
636 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000637 case "module-lib":
638 sdkDirs = []string{"module-lib", "system", "public"}
639 case "system":
640 sdkDirs = []string{"system", "public"}
641 case "public":
642 sdkDirs = []string{"public"}
643 default:
644 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
645 return
satayev783195c2021-06-23 21:49:57 +0100646 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000647
648 for _, sdkDir := range sdkDirs {
649 for _, dir := range dirs {
650 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
651 }
satayev783195c2021-06-23 21:49:57 +0100652 }
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200653
654 if d.properties.Extensions_info_file != nil {
655 if extensions_dir == "" {
656 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
657 }
658 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
659 cmd.Implicit(info_file)
660 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
661 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
662 }
Colin Cross2207f872021-03-24 12:39:08 -0700663}
664
Colin Crosse52c2ac2022-03-28 17:03:35 -0700665func metalavaUseRbe(ctx android.ModuleContext) bool {
666 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
667}
668
Colin Cross2207f872021-03-24 12:39:08 -0700669func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100670 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700671 rule.Command().Text("rm -rf").Flag(homeDir.String())
672 rule.Command().Text("mkdir -p").Flag(homeDir.String())
673
Anton Hansson556e8142021-06-04 16:20:25 +0100674 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700675 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
676
Colin Crosse52c2ac2022-03-28 17:03:35 -0700677 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700678 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700679 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000680 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
681 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700682 labels := map[string]string{"type": "tool", "name": "metalava"}
683 // TODO: metalava pool rejects these jobs
684 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
685 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000686 Labels: labels,
687 ExecStrategy: execStrategy,
688 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
689 Platform: map[string]string{remoteexec.PoolKey: pool},
690 Compare: compare,
691 NumLocalRuns: 1,
692 NumRemoteRuns: 1,
693 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700694 })
Colin Cross2207f872021-03-24 12:39:08 -0700695 }
696
Colin Cross6aa5c402021-03-24 12:28:50 -0700697 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700698 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400699 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100700 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700701 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
702 FlagWithInput("@", srcJarList)
703
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100704 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
705 // years, so it is unlikely to change any time soon.
706 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
707 combinedPaths = append(combinedPaths, classpath.Paths()...)
708 if len(combinedPaths) > 0 {
709 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700710 }
711
Liz Kammere09e20e2023-10-16 15:07:54 -0400712 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000713 if ctx.DeviceConfig().HideFlaggedApis() {
Liz Kammere09e20e2023-10-16 15:07:54 -0400714 cmd.Flag(config.MetalavaHideFlaggedApis)
Jihoon Kangc8313892023-09-20 00:54:47 +0000715 }
716
Colin Cross2207f872021-03-24 12:39:08 -0700717 return cmd
718}
719
Jihoon Kang3c89f042023-12-19 02:40:22 +0000720// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
721// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
722// property is defined, apply transformations and only revert the flagged apis that are not
723// enabled via release configurations and are not specified in aconfig_declarations
724func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
725
726 if len(aconfigFlagsPaths) == 0 {
727 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
728 return
729 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000730
731 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
732 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
733
734 var filterArgs string
735 switch stubsType {
736 // No flagged apis specific flags need to be passed to metalava when generating
737 // everything stubs
738 case Everything:
739 return
740
741 case Runtime:
742 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
743
744 case Exportable:
745 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
746
747 }
748
749 ctx.Build(pctx, android.BuildParams{
750 Rule: gatherReleasedFlaggedApisRule,
751 Inputs: aconfigFlagsPaths,
752 Output: releasedFlaggedApisFile,
753 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
754 Args: map[string]string{
755 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
756 "filter_args": filterArgs,
757 },
758 })
759
760 ctx.Build(pctx, android.BuildParams{
761 Rule: generateMetalavaRevertAnnotationsRule,
762 Input: releasedFlaggedApisFile,
763 Output: revertAnnotationsFile,
764 Description: fmt.Sprintf("%s revert annotations", stubsType),
765 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000766
767 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000768}
769
Jihoon Kang3c89f042023-12-19 02:40:22 +0000770func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
771 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700772 if BoolDefault(d.properties.High_mem, false) {
773 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
774 rule.HighMem()
775 }
776
Jihoon Kang3c89f042023-12-19 02:40:22 +0000777 if params.stubConfig.generateStubs {
778 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
779 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700780 }
781
Jihoon Kang3c89f042023-12-19 02:40:22 +0000782 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700783
Jihoon Kang3c89f042023-12-19 02:40:22 +0000784 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
785 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
786 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700787 cmd.Implicits(d.Javadoc.implicits)
788
Jihoon Kang3c89f042023-12-19 02:40:22 +0000789 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700790
Jihoon Kang3c89f042023-12-19 02:40:22 +0000791 if params.stubConfig.writeSdkValues {
792 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
793 }
794
795 annotationParams := annotationFlagsParams{
796 migratingNullability: params.stubConfig.migratingNullability,
797 validatingNullability: params.stubConfig.validatingNullability,
798 nullabilityWarningsFile: params.nullabilityWarningsFile,
799 annotationsZip: params.annotationsZip,
800 }
801
802 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700803 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000804 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700805
Colin Crossbc139922021-03-25 18:33:16 -0700806 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700807
Colin Cross2207f872021-03-24 12:39:08 -0700808 for _, o := range d.Javadoc.properties.Out {
809 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
810 }
811
Jihoon Kang3c89f042023-12-19 02:40:22 +0000812 return cmd
813}
Colin Cross2207f872021-03-24 12:39:08 -0700814
Jihoon Kang3c89f042023-12-19 02:40:22 +0000815// Sandbox rule for generating the everything stubs and other artifacts
816func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
817 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
818 rule := android.NewRuleBuilder(pctx, ctx)
819 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
820 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
821 SandboxInputs()
822
823 var stubsDir android.OptionalPath
824 if params.generateStubs {
825 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
826 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
827 }
828
829 if params.writeSdkValues {
830 d.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
831 d.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
832 }
833
834 if Bool(d.properties.Annotations_enabled) {
835 if params.validatingNullability {
836 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
837 }
838 d.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
839 }
840 if Bool(d.properties.Api_levels_annotations_enabled) {
841 d.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
842 }
843
844 commonCmdParams := stubsCommandParams{
845 srcJarDir: srcJarDir,
846 stubsDir: stubsDir,
847 stubsSrcJar: d.Javadoc.stubsSrcJar,
848 metadataDir: d.metadataDir,
849 apiVersionsXml: d.apiVersionsXml,
850 nullabilityWarningsFile: d.nullabilityWarningsFile,
851 annotationsZip: d.annotationsZip,
852 stubConfig: params,
853 }
854
855 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
856
857 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
858
859 if params.generateStubs {
860 rule.Command().
861 BuiltTool("soong_zip").
862 Flag("-write_if_changed").
863 Flag("-jar").
864 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
865 FlagWithArg("-C ", stubsDir.String()).
866 FlagWithArg("-D ", stubsDir.String())
867 }
868
869 if params.writeSdkValues {
870 rule.Command().
871 BuiltTool("soong_zip").
872 Flag("-write_if_changed").
873 Flag("-d").
874 FlagWithOutput("-o ", d.metadataZip).
875 FlagWithArg("-C ", d.metadataDir.String()).
876 FlagWithArg("-D ", d.metadataDir.String())
877 }
878
879 // TODO: We don't really need two separate API files, but this is a reminiscence of how
880 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
881 if params.doApiLint {
882 rule.Command().Text("touch").Output(d.apiLintTimestamp)
883 }
884 if params.doCheckReleased {
885 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
886 }
887
888 // TODO(b/183630617): rewrapper doesn't support restat rules
889 if !metalavaUseRbe(ctx) {
890 rule.Restat()
891 }
892
893 zipSyncCleanupCmd(rule, srcJarDir)
894
895 rule.Build("metalava", "metalava merged")
896}
897
898// Sandbox rule for generating the everything artifacts that are not run by
899// default but only run based on the module configurations
900func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700901
902 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000903 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700904 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
905 if newSince.Valid() {
906 cmd.FlagWithInput("--api-lint ", newSince.Path())
907 } else {
908 cmd.Flag("--api-lint")
909 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000910 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700911 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
912
Colin Cross0d532412021-03-25 09:38:45 -0700913 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700914 if d.Name() != "android.car-system-stubs-docs" &&
915 d.Name() != "android.car-stubs-docs" {
916 cmd.Flag("--lints-as-errors")
917 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
918 }
919
920 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000921 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
922 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700923
924 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700925 //
926 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
927 // message and metalava's one?
928 msg := `$'` + // Enclose with $' ... '
929 `************************************************************\n` +
930 `Your API changes are triggering API Lint warnings or errors.\n` +
931 `To make these errors go away, fix the code according to the\n` +
932 `error and/or warning messages above.\n` +
933 `\n` +
934 `If it is not possible to do so, there are workarounds:\n` +
935 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000936 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
937 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700938
939 if baselineFile.Valid() {
940 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
941 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
942
943 msg += fmt.Sprintf(``+
944 `2. You can update the baseline by executing the following\n`+
945 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700946 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
947 ` "%s" \\\n`+
948 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700949 ` To submit the revised baseline.txt to the main Android\n`+
950 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
951 } else {
952 msg += fmt.Sprintf(``+
953 `2. You can add a baseline file of existing lint failures\n`+
954 ` to the build rule of %s.\n`, d.Name())
955 }
956 // Note the message ends with a ' (single quote), to close the $' ... ' .
957 msg += `************************************************************\n'`
958
959 cmd.FlagWithArg("--error-message:api-lint ", msg)
960 }
961
962 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000963 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700964 if len(d.Javadoc.properties.Out) > 0 {
965 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
966 }
967
968 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
969 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
970 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000971 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700972
Jihoon Kang3c89f042023-12-19 02:40:22 +0000973 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700974
975 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
976 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
977
978 if baselineFile.Valid() {
979 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
980 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
981 }
982
983 // Note this string includes quote ($' ... '), which decodes the "\n"s.
984 msg := `$'\n******************************\n` +
985 `You have tried to change the API from what has been previously released in\n` +
986 `an SDK. Please fix the errors listed above.\n` +
987 `******************************\n'`
988
989 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
990 }
991
Paul Duffin10a23c22023-08-11 22:47:31 +0100992 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
993 // Pass the current API file into metalava so it can use it as the basis for determining how to
994 // generate the output signature files (both api and removed).
995 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
996 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
997 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000998}
Paul Duffin10a23c22023-08-11 22:47:31 +0100999
Jihoon Kang3c89f042023-12-19 02:40:22 +00001000// Sandbox rule for generating exportable stubs and other artifacts
1001func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1002 optionalCmdParams := stubsCommandParams{
1003 stubConfig: params,
1004 }
1005
1006 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1007 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1008 if params.writeSdkValues {
1009 d.exportableMetadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1010 d.exportableMetadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1011 optionalCmdParams.metadataZip = d.exportableMetadataZip
1012 optionalCmdParams.metadataDir = d.exportableMetadataDir
1013 }
1014
1015 if Bool(d.properties.Annotations_enabled) {
1016 if params.validatingNullability {
1017 d.exportableNullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1018 optionalCmdParams.nullabilityWarningsFile = d.exportableNullabilityWarningsFile
1019 }
1020 d.exportableAnnotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1021 optionalCmdParams.annotationsZip = d.exportableAnnotationsZip
1022 }
1023 if Bool(d.properties.Api_levels_annotations_enabled) {
1024 d.exportableApiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1025 optionalCmdParams.apiVersionsXml = d.exportableApiVersionsXml
1026 }
1027
1028 if params.checkApi || String(d.properties.Api_filename) != "" {
1029 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1030 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1031 }
1032
1033 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1034 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1035 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1036 }
1037
1038 d.optionalStubCmd(ctx, optionalCmdParams)
1039}
1040
1041func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1042
1043 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1044 rule := android.NewRuleBuilder(pctx, ctx)
1045 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1046 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1047 SandboxInputs()
1048
1049 if params.stubConfig.generateStubs {
1050 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1051 }
1052
1053 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1054
1055 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1056
1057 if params.stubConfig.doApiLint {
1058 // Pass the lint baseline file as an input to resolve the lint errors.
1059 // The exportable stubs generation does not update the lint baseline file.
1060 // Lint baseline file update is handled by the everything stubs
1061 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1062 if baselineFile.Valid() {
1063 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1064 }
1065 }
1066
1067 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001068 rule.Command().
1069 BuiltTool("soong_zip").
1070 Flag("-write_if_changed").
1071 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001072 FlagWithOutput("-o ", params.stubsSrcJar).
1073 FlagWithArg("-C ", params.stubsDir.String()).
1074 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001075 }
1076
Jihoon Kang3c89f042023-12-19 02:40:22 +00001077 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001078 rule.Command().
1079 BuiltTool("soong_zip").
1080 Flag("-write_if_changed").
1081 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001082 FlagWithOutput("-o ", params.metadataZip).
1083 FlagWithArg("-C ", params.metadataDir.String()).
1084 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001085 }
1086
Colin Cross6aa5c402021-03-24 12:28:50 -07001087 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001088 if !metalavaUseRbe(ctx) {
1089 rule.Restat()
1090 }
Colin Cross2207f872021-03-24 12:39:08 -07001091
Jihoon Kang3c89f042023-12-19 02:40:22 +00001092 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001093
Jihoon Kang3c89f042023-12-19 02:40:22 +00001094 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1095}
1096
1097func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1098 deps := d.Javadoc.collectDeps(ctx)
1099
1100 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1101 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1102
1103 // Add options for the other optional tasks: API-lint and check-released.
1104 // We generate separate timestamp files for them.
1105 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1106 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1107
1108 writeSdkValues := Bool(d.properties.Write_sdk_values)
1109
1110 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1111
1112 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1113 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1114 String(d.properties.Validate_nullability_from_list) != "")
1115
1116 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1117 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1118
1119 stubCmdParams := stubsCommandConfigParams{
1120 javaVersion: javaVersion,
1121 deps: deps,
1122 checkApi: checkApi,
1123 generateStubs: generateStubs,
1124 doApiLint: doApiLint,
1125 doCheckReleased: doCheckReleased,
1126 writeSdkValues: writeSdkValues,
1127 migratingNullability: migratingNullability,
1128 validatingNullability: validatingNullability,
1129 }
1130 stubCmdParams.stubsType = Everything
1131 // Create default (i.e. "everything" stubs) rule for metalava
1132 d.everythingStubCmd(ctx, stubCmdParams)
1133
1134 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
1135 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1136 // strips all flagged apis to generate the "exportable" stubs
1137 stubCmdParams.stubsType = Exportable
1138 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001139
Paul Duffine7a86642022-08-16 15:43:20 +00001140 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1141
1142 if len(d.Javadoc.properties.Out) > 0 {
1143 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1144 }
1145
1146 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1147 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1148 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1149
1150 if baselineFile.Valid() {
1151 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1152 }
1153
Jihoon Kang3c89f042023-12-19 02:40:22 +00001154 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001155
1156 rule := android.NewRuleBuilder(pctx, ctx)
1157
1158 // Diff command line.
1159 // -F matches the closest "opening" line, such as "package android {"
1160 // and " public class Intent {".
1161 diff := `diff -u -F '{ *$'`
1162
1163 rule.Command().Text("( true")
1164 rule.Command().
1165 Text(diff).
1166 Input(apiFile).Input(d.apiFile)
1167
1168 rule.Command().
1169 Text(diff).
1170 Input(removedApiFile).Input(d.removedApiFile)
1171
1172 msg := fmt.Sprintf(`\n******************************\n`+
1173 `You have tried to change the API from what has been previously approved.\n\n`+
1174 `To make these errors go away, you have two choices:\n`+
1175 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1176 ` to the new methods, etc. shown in the above diff.\n\n`+
1177 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1178 ` m %s-update-current-api\n\n`+
1179 ` To submit the revised current.txt to the main Android repository,\n`+
1180 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001181 `If your build failed due to stub validation, you can resolve the errors with\n`+
1182 `either of the two choices above and try re-building the target.\n`+
1183 `If the mismatch between the stubs and the current.txt is intended,\n`+
1184 `you can try re-building the target by executing the following command:\n`+
1185 `m DISABLE_STUB_VALIDATION=true <your build target>\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001186 `******************************\n`, ctx.ModuleName())
1187
1188 rule.Command().
1189 Text("touch").Output(d.checkCurrentApiTimestamp).
1190 Text(") || (").
1191 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1192 Text("; exit 38").
1193 Text(")")
1194
1195 rule.Build("metalavaCurrentApiCheck", "check current API")
1196
Jihoon Kang3c89f042023-12-19 02:40:22 +00001197 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001198
1199 // update API rule
1200 rule = android.NewRuleBuilder(pctx, ctx)
1201
1202 rule.Command().Text("( true")
1203
1204 rule.Command().
1205 Text("cp").Flag("-f").
1206 Input(d.apiFile).Flag(apiFile.String())
1207
1208 rule.Command().
1209 Text("cp").Flag("-f").
1210 Input(d.removedApiFile).Flag(removedApiFile.String())
1211
1212 msg = "failed to update public API"
1213
1214 rule.Command().
1215 Text("touch").Output(d.updateCurrentApiTimestamp).
1216 Text(") || (").
1217 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1218 Text("; exit 38").
1219 Text(")")
1220
1221 rule.Build("metalavaCurrentApiUpdate", "update current API")
1222 }
1223
Colin Cross2207f872021-03-24 12:39:08 -07001224 if String(d.properties.Check_nullability_warnings) != "" {
1225 if d.nullabilityWarningsFile == nil {
1226 ctx.PropertyErrorf("check_nullability_warnings",
1227 "Cannot specify check_nullability_warnings unless validating nullability")
1228 }
1229
1230 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1231
Jihoon Kang3c89f042023-12-19 02:40:22 +00001232 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001233
1234 msg := fmt.Sprintf(`\n******************************\n`+
1235 `The warnings encountered during nullability annotation validation did\n`+
1236 `not match the checked in file of expected warnings. The diffs are shown\n`+
1237 `above. You have two options:\n`+
1238 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1239 ` 2. Update the file of expected warnings by running:\n`+
1240 ` cp %s %s\n`+
1241 ` and submitting the updated file as part of your change.`,
1242 d.nullabilityWarningsFile, checkNullabilityWarnings)
1243
1244 rule := android.NewRuleBuilder(pctx, ctx)
1245
1246 rule.Command().
1247 Text("(").
1248 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
1249 Text("&&").
1250 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1251 Text(") || (").
1252 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1253 Text("; exit 38").
1254 Text(")")
1255
1256 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1257 }
1258}
1259
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001260func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1261 api_file := d.properties.Check_api.Current.Api_file
1262 api_surface := d.properties.Api_surface
1263
1264 props := struct {
1265 Name *string
1266 Api_surface *string
1267 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001268 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001269 }{}
1270
1271 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1272 props.Api_surface = api_surface
1273 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001274 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001275
1276 ctx.CreateModule(ApiContributionFactory, &props)
1277}
1278
Spandan Das0b555e32022-11-28 18:48:51 +00001279// TODO (b/262014796): Export the API contributions of CorePlatformApi
1280// A map to populate the api surface of a droidstub from a substring appearing in its name
1281// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1282// use a strict naming convention
1283var (
1284 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1285 //public is commented out since the core libraries use public in their java_sdk_library names
1286 "intracore": android.SdkIntraCore,
1287 "intra.core": android.SdkIntraCore,
1288 "system_server": android.SdkSystemServer,
1289 "system-server": android.SdkSystemServer,
1290 "system": android.SdkSystem,
1291 "module_lib": android.SdkModule,
1292 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001293 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001294 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001295 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001296 }
1297)
1298
Colin Cross2207f872021-03-24 12:39:08 -07001299func StubsDefaultsFactory() android.Module {
1300 module := &DocDefaults{}
1301
1302 module.AddProperties(
1303 &JavadocProperties{},
1304 &DroidstubsProperties{},
1305 )
1306
1307 android.InitDefaultsModule(module)
1308
1309 return module
1310}
1311
1312var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1313
1314type PrebuiltStubsSourcesProperties struct {
1315 Srcs []string `android:"path"`
1316}
1317
1318type PrebuiltStubsSources struct {
1319 android.ModuleBase
1320 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001321 embeddableInModuleAndImport
1322
Colin Cross2207f872021-03-24 12:39:08 -07001323 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001324
1325 properties PrebuiltStubsSourcesProperties
1326
kgui67007242022-01-25 13:50:25 +08001327 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001328}
1329
1330func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1331 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001332 // prebuilt droidstubs does not output "exportable" stubs.
1333 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1334 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001335 return android.Paths{p.stubsSrcJar}, nil
1336 default:
1337 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1338 }
1339}
1340
1341func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
1342 return d.stubsSrcJar
1343}
1344
1345func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001346 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001347 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 -07001348 return
1349 }
1350
Anton Hansson86758ac2021-11-03 14:44:12 +00001351 src := p.properties.Srcs[0]
1352 if filepath.Ext(src) == ".srcjar" {
1353 // This is a srcjar. We can use it directly.
1354 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1355 } else {
1356 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001357
Anton Hansson86758ac2021-11-03 14:44:12 +00001358 // This is a directory. Glob the contents just in case the directory does not exist.
1359 srcGlob := src + "/**/*"
1360 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001361
Anton Hansson86758ac2021-11-03 14:44:12 +00001362 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1363 // the path components are invalid it won't in this case because no components
1364 // are specified and the module directory must exist in order to get this far.
1365 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001366
Anton Hansson86758ac2021-11-03 14:44:12 +00001367 rule := android.NewRuleBuilder(pctx, ctx)
1368 rule.Command().
1369 BuiltTool("soong_zip").
1370 Flag("-write_if_changed").
1371 Flag("-jar").
1372 FlagWithOutput("-o ", outPath).
1373 FlagWithArg("-C ", srcDir.String()).
1374 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1375 rule.Restat()
1376 rule.Build("zip src", "Create srcjar from prebuilt source")
1377 p.stubsSrcJar = outPath
1378 }
Colin Cross2207f872021-03-24 12:39:08 -07001379}
1380
1381func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1382 return &p.prebuilt
1383}
1384
1385func (p *PrebuiltStubsSources) Name() string {
1386 return p.prebuilt.Name(p.ModuleBase.Name())
1387}
1388
1389// prebuilt_stubs_sources imports a set of java source files as if they were
1390// generated by droidstubs.
1391//
1392// By default, a prebuilt_stubs_sources has a single variant that expects a
1393// set of `.java` files generated by droidstubs.
1394//
1395// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1396// for host modules.
1397//
1398// Intended only for use by sdk snapshots.
1399func PrebuiltStubsSourcesFactory() android.Module {
1400 module := &PrebuiltStubsSources{}
1401
1402 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001403 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001404
1405 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001406 InitDroiddocModule(module, android.HostAndDeviceSupported)
1407 return module
1408}