blob: 04e6be8d7f4c5806f4adbbda7cabe5066b9cf4b5 [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
LaMont Jonesafe7baf2024-01-09 22:47:39 +000092 // Single aconfig "cache file" merged from this module and all dependencies.
93 mergedAconfigFiles map[string]android.Paths
94
Jihoon Kang3c89f042023-12-19 02:40:22 +000095 exportableApiFile android.WritablePath
96 exportableRemovedApiFile android.WritablePath
97 exportableNullabilityWarningsFile android.WritablePath
98 exportableAnnotationsZip android.WritablePath
99 exportableApiVersionsXml android.WritablePath
100 exportableMetadataZip android.WritablePath
101 exportableMetadataDir android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700102}
103
104type DroidstubsProperties struct {
105 // The generated public API filename by Metalava, defaults to <module>_api.txt
106 Api_filename *string
107
108 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
109 Removed_api_filename *string
110
Colin Cross2207f872021-03-24 12:39:08 -0700111 Check_api struct {
112 Last_released ApiToCheck
113
114 Current ApiToCheck
115
116 Api_lint struct {
117 Enabled *bool
118
119 // If set, performs api_lint on any new APIs not found in the given signature file
120 New_since *string `android:"path"`
121
122 // If not blank, path to the baseline txt file for approved API lint violations.
123 Baseline_file *string `android:"path"`
124 }
125 }
126
127 // user can specify the version of previous released API file in order to do compatibility check.
128 Previous_api *string `android:"path"`
129
130 // is set to true, Metalava will allow framework SDK to contain annotations.
131 Annotations_enabled *bool
132
133 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
134 Merge_annotations_dirs []string
135
136 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
137 Merge_inclusion_annotations_dirs []string
138
139 // a file containing a list of classes to do nullability validation for.
140 Validate_nullability_from_list *string
141
142 // a file containing expected warnings produced by validation of nullability annotations.
143 Check_nullability_warnings *string
144
145 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
146 Create_doc_stubs *bool
147
148 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
149 // Has no effect if create_doc_stubs: true.
150 Output_javadoc_comments *bool
151
152 // if set to false then do not write out stubs. Defaults to true.
153 //
154 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
155 Generate_stubs *bool
156
157 // 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 -0400158 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700159 High_mem *bool
160
satayev783195c2021-06-23 21:49:57 +0100161 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700162 Api_levels_annotations_enabled *bool
163
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000164 // Apply the api levels database created by this module rather than generating one in this droidstubs.
165 Api_levels_module *string
166
Colin Cross2207f872021-03-24 12:39:08 -0700167 // the dirs which Metalava extracts API levels annotations from.
168 Api_levels_annotations_dirs []string
169
Cole Faust051fa912022-10-05 12:45:42 -0700170 // 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 +0100171 Api_levels_sdk_type *string
172
Colin Cross2207f872021-03-24 12:39:08 -0700173 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
174 Api_levels_jar_filename *string
175
176 // if set to true, collect the values used by the Dev tools and
177 // write them in files packaged with the SDK. Defaults to false.
178 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200179
180 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
181 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
182 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000183
184 // API surface of this module. If set, the module contributes to an API surface.
185 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
186 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000187
188 // a list of aconfig_declarations module names that the stubs generated in this module
189 // depend on.
190 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700191}
192
Anton Hansson52609322021-05-05 10:36:05 +0100193// Used by xsd_config
194type ApiFilePath interface {
195 ApiFilePath() android.Path
196}
197
198type ApiStubsSrcProvider interface {
199 StubsSrcJar() android.Path
200}
201
202// Provider of information about API stubs, used by java_sdk_library.
203type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100204 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100205 ApiFilePath
206 RemovedApiFilePath() android.Path
207
208 ApiStubsSrcProvider
209}
210
Jihoon Kang063ec002023-06-28 01:16:23 +0000211type currentApiTimestampProvider interface {
212 CurrentApiTimestamp() android.Path
213}
214
Jihoon Kang3c89f042023-12-19 02:40:22 +0000215type annotationFlagsParams struct {
216 migratingNullability bool
217 validatingNullability bool
218 nullabilityWarningsFile android.WritablePath
219 annotationsZip android.WritablePath
220}
221type stubsCommandParams struct {
222 srcJarDir android.ModuleOutPath
223 stubsDir android.OptionalPath
224 stubsSrcJar android.WritablePath
225 metadataZip android.WritablePath
226 metadataDir android.WritablePath
227 apiVersionsXml android.WritablePath
228 nullabilityWarningsFile android.WritablePath
229 annotationsZip android.WritablePath
230 stubConfig stubsCommandConfigParams
231}
232type stubsCommandConfigParams struct {
233 stubsType StubsType
234 javaVersion javaVersion
235 deps deps
236 checkApi bool
237 generateStubs bool
238 doApiLint bool
239 doCheckReleased bool
240 writeSdkValues bool
241 migratingNullability bool
242 validatingNullability bool
243}
244
Colin Cross2207f872021-03-24 12:39:08 -0700245// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
246// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
247// a droiddoc module to generate documentation.
248func DroidstubsFactory() android.Module {
249 module := &Droidstubs{}
250
251 module.AddProperties(&module.properties,
252 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000253 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700254
255 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000256
257 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
258 module.createApiContribution(ctx)
259 })
Colin Cross2207f872021-03-24 12:39:08 -0700260 return module
261}
262
263// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
264// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
265// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
266// module when symbols needed by the source files are provided by java_library_host modules.
267func DroidstubsHostFactory() android.Module {
268 module := &Droidstubs{}
269
270 module.AddProperties(&module.properties,
271 &module.Javadoc.properties)
272
273 InitDroiddocModule(module, android.HostSupported)
274 return module
275}
276
Jihoon Kang78f89142023-12-27 01:40:29 +0000277func getStubsTypeAndTag(tag string) (StubsType, string, error) {
278 if len(tag) == 0 {
279 return Everything, "", nil
280 }
281 if tag[0] != '.' {
282 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
283 }
284
285 stubsType := Everything
286 // Check if the tag has a stubs type prefix (e.g. ".exportable")
287 for st := Everything; st <= Exportable; st++ {
288 if strings.HasPrefix(tag, "."+st.String()) {
289 stubsType = st
290 }
291 }
292
293 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
294}
295
296// Droidstubs' tag supports specifying with the stubs type.
297// While supporting the pre-existing tags, it also supports tags with
298// the stubs type prefix. Some examples are shown below:
299// {.annotations.zip} - pre-existing behavior. Returns the path to the
300// annotation zip.
301// {.exportable} - Returns the path to the exportable stubs src jar.
302// {.exportable.annotations.zip} - Returns the path to the exportable
303// annotations zip file.
304// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
305// xml file. For unsupported combinations, the default everything output file
306// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700307func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000308 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
309 if err != nil {
310 return nil, err
311 }
312 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700313 case "":
Jihoon Kang78f89142023-12-27 01:40:29 +0000314 return d.StubsSrcJarWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700315 case ".docs.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000316 return d.DocZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700317 case ".api.txt", android.DefaultDistTag:
318 // This is the default dist path for dist properties that have no tag property.
Jihoon Kang78f89142023-12-27 01:40:29 +0000319 return d.ApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700320 case ".removed-api.txt":
Jihoon Kang78f89142023-12-27 01:40:29 +0000321 return d.RemovedApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700322 case ".annotations.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000323 return d.AnnotationsZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700324 case ".api_versions.xml":
Jihoon Kang78f89142023-12-27 01:40:29 +0000325 return d.ApiVersionsXmlFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700326 default:
327 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
328 }
329}
330
Anton Hanssond78eb762021-09-21 15:25:12 +0100331func (d *Droidstubs) AnnotationsZip() android.Path {
332 return d.annotationsZip
333}
334
Jihoon Kang78f89142023-12-27 01:40:29 +0000335func (d *Droidstubs) ExportableAnnotationsZip() android.Path {
336 return d.exportableAnnotationsZip
337}
338
339func (d *Droidstubs) AnnotationsZipWithStubsType(stubsType StubsType) (android.Paths, error) {
340 switch stubsType {
341 case Everything:
342 return android.Paths{d.AnnotationsZip()}, nil
343 case Exportable:
344 return android.Paths{d.ExportableAnnotationsZip()}, nil
345 default:
346 return nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
347 }
348}
349
Colin Cross2207f872021-03-24 12:39:08 -0700350func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000351 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700352}
353
Jihoon Kang78f89142023-12-27 01:40:29 +0000354func (d *Droidstubs) ExportableApiFilePath() android.Path {
355 return d.exportableApiFile
356}
357
358func (d *Droidstubs) ApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
359 switch stubsType {
360 case Everything:
361 return android.Paths{d.ApiFilePath()}, nil
362 case Exportable:
363 return android.Paths{d.ExportableApiFilePath()}, nil
364 default:
365 return nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
366 }
367}
368
369func (d *Droidstubs) ApiVersionsXmlFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
370 switch stubsType {
371 case Everything:
372 return android.Paths{d.apiVersionsXml}, nil
373 default:
374 return nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
375 }
376}
377
378func (d *Droidstubs) DocZipWithStubsType(stubsType StubsType) (android.Paths, error) {
379 switch stubsType {
380 case Everything:
381 return android.Paths{d.docZip}, nil
382 default:
383 return nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
384 }
385}
386
Colin Cross2207f872021-03-24 12:39:08 -0700387func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000388 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700389}
390
Jihoon Kang78f89142023-12-27 01:40:29 +0000391func (d *Droidstubs) ExportableRemovedApiFilePath() android.Path {
392 return d.exportableRemovedApiFile
393}
394
395func (d *Droidstubs) RemovedApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
396 switch stubsType {
397 case Everything:
398 return android.Paths{d.RemovedApiFilePath()}, nil
399 case Exportable:
400 return android.Paths{d.ExportableRemovedApiFilePath()}, nil
401 default:
402 return nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
403 }
404}
405
Colin Cross2207f872021-03-24 12:39:08 -0700406func (d *Droidstubs) StubsSrcJar() android.Path {
407 return d.stubsSrcJar
408}
409
Jihoon Kang78f89142023-12-27 01:40:29 +0000410func (d *Droidstubs) ExportableStubsSrcJar() android.Path {
411 return d.exportableStubsSrcJar
412}
413
414func (d *Droidstubs) StubsSrcJarWithStubsType(stubsType StubsType) (android.Paths, error) {
415 switch stubsType {
416 case Everything:
417 return android.Paths{d.StubsSrcJar()}, nil
418 case Exportable:
419 return android.Paths{d.ExportableStubsSrcJar()}, nil
420 default:
421 return nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
422 }
423}
424
Jihoon Kang063ec002023-06-28 01:16:23 +0000425func (d *Droidstubs) CurrentApiTimestamp() android.Path {
426 return d.checkCurrentApiTimestamp
427}
428
Colin Cross2207f872021-03-24 12:39:08 -0700429var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
430var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
431var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000432var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000433var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700434
435func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
436 d.Javadoc.addDeps(ctx)
437
438 if len(d.properties.Merge_annotations_dirs) != 0 {
439 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
440 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
441 }
442 }
443
444 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
445 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
446 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
447 }
448 }
449
450 if len(d.properties.Api_levels_annotations_dirs) != 0 {
451 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
452 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
453 }
454 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000455
Jihoon Kang6592e872023-12-19 01:13:16 +0000456 if len(d.properties.Aconfig_declarations) != 0 {
457 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
458 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
459 }
460 }
461
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000462 if d.properties.Api_levels_module != nil {
463 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
464 }
Colin Cross2207f872021-03-24 12:39:08 -0700465}
466
Jihoon Kang3c89f042023-12-19 02:40:22 +0000467func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
468 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
469}
470
471func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
472 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700473 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000474 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000475 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000476
477 if stubsType == Everything {
478 d.apiFile = uncheckedApiFile
479 } else if stubsType == Exportable {
480 d.exportableApiFile = uncheckedApiFile
481 }
Colin Cross2207f872021-03-24 12:39:08 -0700482 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
483 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000484 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700485 }
486
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700488 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000489 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000490 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000491
492 if stubsType == Everything {
493 d.removedApiFile = uncheckedRemovedFile
494 } else if stubsType == Exportable {
495 d.exportableRemovedApiFile = uncheckedRemovedFile
496 }
Colin Cross2207f872021-03-24 12:39:08 -0700497 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
498 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000499 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700500 }
501
Colin Cross2207f872021-03-24 12:39:08 -0700502 if stubsDir.Valid() {
503 if Bool(d.properties.Create_doc_stubs) {
504 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
505 } else {
506 cmd.FlagWithArg("--stubs ", stubsDir.String())
507 if !Bool(d.properties.Output_javadoc_comments) {
508 cmd.Flag("--exclude-documentation-from-stubs")
509 }
510 }
511 }
512}
513
Jihoon Kang3c89f042023-12-19 02:40:22 +0000514func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Colin Cross2207f872021-03-24 12:39:08 -0700515 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400516 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100517
Jihoon Kang3c89f042023-12-19 02:40:22 +0000518 if params.migratingNullability {
Colin Cross2207f872021-03-24 12:39:08 -0700519 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
520 cmd.FlagWithInput("--migrate-nullness ", previousApi)
521 }
522
523 if s := String(d.properties.Validate_nullability_from_list); s != "" {
524 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
525 }
526
Jihoon Kang3c89f042023-12-19 02:40:22 +0000527 if params.validatingNullability {
528 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
Colin Cross2207f872021-03-24 12:39:08 -0700529 }
530
Jihoon Kang3c89f042023-12-19 02:40:22 +0000531 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Colin Cross2207f872021-03-24 12:39:08 -0700532
533 if len(d.properties.Merge_annotations_dirs) != 0 {
534 d.mergeAnnoDirFlags(ctx, cmd)
535 }
536
Liz Kammere09e20e2023-10-16 15:07:54 -0400537 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700538 }
539}
540
541func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
542 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
543 if t, ok := m.(*ExportedDroiddocDir); ok {
544 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
545 } else {
546 ctx.PropertyErrorf("merge_annotations_dirs",
547 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
548 }
549 })
550}
551
552func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
553 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
554 if t, ok := m.(*ExportedDroiddocDir); ok {
555 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
556 } else {
557 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
558 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
559 }
560 })
561}
562
Jihoon Kang3c89f042023-12-19 02:40:22 +0000563func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000564 var apiVersions android.Path
565 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000566 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000567 apiVersions = d.apiVersionsXml
568 } else {
569 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
570 if s, ok := m.(*Droidstubs); ok {
571 apiVersions = s.apiVersionsXml
572 } else {
573 ctx.PropertyErrorf("api_levels_module",
574 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
575 }
576 })
Colin Cross2207f872021-03-24 12:39:08 -0700577 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000578 if apiVersions != nil {
579 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
580 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
581 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
582 }
583}
Colin Cross2207f872021-03-24 12:39:08 -0700584
Jihoon Kang3c89f042023-12-19 02:40:22 +0000585func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700586 if len(d.properties.Api_levels_annotations_dirs) == 0 {
587 ctx.PropertyErrorf("api_levels_annotations_dirs",
588 "has to be non-empty if api levels annotations was enabled!")
589 }
590
Jihoon Kang3c89f042023-12-19 02:40:22 +0000591 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700592
593 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
594
satayev783195c2021-06-23 21:49:57 +0100595 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200596 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700597 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
598 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200599 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
600
601 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
602 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700603 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200604 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
605 if extensions_dir == "" {
606 extensions_dir = t.dir.String() + "/extensions"
607 }
608 cmd.Implicit(dep)
609 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700610 if dep.Base() == filename {
611 cmd.Implicit(dep)
612 }
613 if filename != "android.jar" && dep.Base() == "android.jar" {
614 // Metalava implicitly searches these patterns:
615 // prebuilts/tools/common/api-versions/android-%/android.jar
616 // prebuilts/sdk/%/public/android.jar
617 // Add android.jar files from the api_levels_annotations_dirs directories to try
618 // to satisfy these patterns. If Metalava can't find a match for an API level
619 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700620 cmd.Implicit(dep)
621 }
622 }
satayev783195c2021-06-23 21:49:57 +0100623
624 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700625 } else {
626 ctx.PropertyErrorf("api_levels_annotations_dirs",
627 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
628 }
629 })
satayev783195c2021-06-23 21:49:57 +0100630
631 // Add all relevant --android-jar-pattern patterns for Metalava.
632 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
633 // an actual file present on disk (in the order the patterns were passed). For system APIs for
634 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000635 // for older releases. Similarly, module-lib falls back to system API.
636 var sdkDirs []string
637 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700638 case "system-server":
639 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000640 case "module-lib":
641 sdkDirs = []string{"module-lib", "system", "public"}
642 case "system":
643 sdkDirs = []string{"system", "public"}
644 case "public":
645 sdkDirs = []string{"public"}
646 default:
647 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
648 return
satayev783195c2021-06-23 21:49:57 +0100649 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000650
651 for _, sdkDir := range sdkDirs {
652 for _, dir := range dirs {
653 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
654 }
satayev783195c2021-06-23 21:49:57 +0100655 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200656
657 if d.properties.Extensions_info_file != nil {
658 if extensions_dir == "" {
659 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
660 }
661 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
662 cmd.Implicit(info_file)
663 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
664 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
665 }
Colin Cross2207f872021-03-24 12:39:08 -0700666}
667
Colin Crosse52c2ac2022-03-28 17:03:35 -0700668func metalavaUseRbe(ctx android.ModuleContext) bool {
669 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
670}
671
Colin Cross2207f872021-03-24 12:39:08 -0700672func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100673 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700674 rule.Command().Text("rm -rf").Flag(homeDir.String())
675 rule.Command().Text("mkdir -p").Flag(homeDir.String())
676
Anton Hansson556e8142021-06-04 16:20:25 +0100677 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700678 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
679
Colin Crosse52c2ac2022-03-28 17:03:35 -0700680 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700681 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700682 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000683 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
684 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700685 labels := map[string]string{"type": "tool", "name": "metalava"}
686 // TODO: metalava pool rejects these jobs
687 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
688 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000689 Labels: labels,
690 ExecStrategy: execStrategy,
691 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
692 Platform: map[string]string{remoteexec.PoolKey: pool},
693 Compare: compare,
694 NumLocalRuns: 1,
695 NumRemoteRuns: 1,
696 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700697 })
Colin Cross2207f872021-03-24 12:39:08 -0700698 }
699
Colin Cross6aa5c402021-03-24 12:28:50 -0700700 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700701 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400702 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100703 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700704 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
705 FlagWithInput("@", srcJarList)
706
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100707 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
708 // years, so it is unlikely to change any time soon.
709 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
710 combinedPaths = append(combinedPaths, classpath.Paths()...)
711 if len(combinedPaths) > 0 {
712 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700713 }
714
Liz Kammere09e20e2023-10-16 15:07:54 -0400715 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000716 if ctx.DeviceConfig().HideFlaggedApis() {
Liz Kammere09e20e2023-10-16 15:07:54 -0400717 cmd.Flag(config.MetalavaHideFlaggedApis)
Jihoon Kangc8313892023-09-20 00:54:47 +0000718 }
719
Colin Cross2207f872021-03-24 12:39:08 -0700720 return cmd
721}
722
Jihoon Kang3c89f042023-12-19 02:40:22 +0000723// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
724// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
725// property is defined, apply transformations and only revert the flagged apis that are not
726// enabled via release configurations and are not specified in aconfig_declarations
727func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
728
729 if len(aconfigFlagsPaths) == 0 {
730 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
731 return
732 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000733
734 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
735 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
736
737 var filterArgs string
738 switch stubsType {
739 // No flagged apis specific flags need to be passed to metalava when generating
740 // everything stubs
741 case Everything:
742 return
743
744 case Runtime:
745 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
746
747 case Exportable:
748 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
749
750 }
751
752 ctx.Build(pctx, android.BuildParams{
753 Rule: gatherReleasedFlaggedApisRule,
754 Inputs: aconfigFlagsPaths,
755 Output: releasedFlaggedApisFile,
756 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
757 Args: map[string]string{
758 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
759 "filter_args": filterArgs,
760 },
761 })
762
763 ctx.Build(pctx, android.BuildParams{
764 Rule: generateMetalavaRevertAnnotationsRule,
765 Input: releasedFlaggedApisFile,
766 Output: revertAnnotationsFile,
767 Description: fmt.Sprintf("%s revert annotations", stubsType),
768 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000769
770 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000771}
772
Jihoon Kang3c89f042023-12-19 02:40:22 +0000773func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
774 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700775 if BoolDefault(d.properties.High_mem, false) {
776 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
777 rule.HighMem()
778 }
779
Jihoon Kang3c89f042023-12-19 02:40:22 +0000780 if params.stubConfig.generateStubs {
781 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
782 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700783 }
784
Jihoon Kang3c89f042023-12-19 02:40:22 +0000785 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700786
Jihoon Kang3c89f042023-12-19 02:40:22 +0000787 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
788 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
789 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700790 cmd.Implicits(d.Javadoc.implicits)
791
Jihoon Kang3c89f042023-12-19 02:40:22 +0000792 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700793
Jihoon Kang3c89f042023-12-19 02:40:22 +0000794 if params.stubConfig.writeSdkValues {
795 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
796 }
797
798 annotationParams := annotationFlagsParams{
799 migratingNullability: params.stubConfig.migratingNullability,
800 validatingNullability: params.stubConfig.validatingNullability,
801 nullabilityWarningsFile: params.nullabilityWarningsFile,
802 annotationsZip: params.annotationsZip,
803 }
804
805 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700806 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000807 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700808
Colin Crossbc139922021-03-25 18:33:16 -0700809 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700810
Colin Cross2207f872021-03-24 12:39:08 -0700811 for _, o := range d.Javadoc.properties.Out {
812 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
813 }
814
Jihoon Kang3c89f042023-12-19 02:40:22 +0000815 return cmd
816}
Colin Cross2207f872021-03-24 12:39:08 -0700817
Jihoon Kang3c89f042023-12-19 02:40:22 +0000818// Sandbox rule for generating the everything stubs and other artifacts
819func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
820 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
821 rule := android.NewRuleBuilder(pctx, ctx)
822 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
823 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
824 SandboxInputs()
825
826 var stubsDir android.OptionalPath
827 if params.generateStubs {
828 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
829 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
830 }
831
832 if params.writeSdkValues {
833 d.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
834 d.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
835 }
836
837 if Bool(d.properties.Annotations_enabled) {
838 if params.validatingNullability {
839 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
840 }
841 d.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
842 }
843 if Bool(d.properties.Api_levels_annotations_enabled) {
844 d.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
845 }
846
847 commonCmdParams := stubsCommandParams{
848 srcJarDir: srcJarDir,
849 stubsDir: stubsDir,
850 stubsSrcJar: d.Javadoc.stubsSrcJar,
851 metadataDir: d.metadataDir,
852 apiVersionsXml: d.apiVersionsXml,
853 nullabilityWarningsFile: d.nullabilityWarningsFile,
854 annotationsZip: d.annotationsZip,
855 stubConfig: params,
856 }
857
858 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
859
860 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
861
862 if params.generateStubs {
863 rule.Command().
864 BuiltTool("soong_zip").
865 Flag("-write_if_changed").
866 Flag("-jar").
867 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
868 FlagWithArg("-C ", stubsDir.String()).
869 FlagWithArg("-D ", stubsDir.String())
870 }
871
872 if params.writeSdkValues {
873 rule.Command().
874 BuiltTool("soong_zip").
875 Flag("-write_if_changed").
876 Flag("-d").
877 FlagWithOutput("-o ", d.metadataZip).
878 FlagWithArg("-C ", d.metadataDir.String()).
879 FlagWithArg("-D ", d.metadataDir.String())
880 }
881
882 // TODO: We don't really need two separate API files, but this is a reminiscence of how
883 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
884 if params.doApiLint {
885 rule.Command().Text("touch").Output(d.apiLintTimestamp)
886 }
887 if params.doCheckReleased {
888 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
889 }
890
891 // TODO(b/183630617): rewrapper doesn't support restat rules
892 if !metalavaUseRbe(ctx) {
893 rule.Restat()
894 }
895
896 zipSyncCleanupCmd(rule, srcJarDir)
897
898 rule.Build("metalava", "metalava merged")
899}
900
901// Sandbox rule for generating the everything artifacts that are not run by
902// default but only run based on the module configurations
903func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700904
905 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000906 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700907 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
908 if newSince.Valid() {
909 cmd.FlagWithInput("--api-lint ", newSince.Path())
910 } else {
911 cmd.Flag("--api-lint")
912 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000913 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700914 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
915
Colin Cross0d532412021-03-25 09:38:45 -0700916 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700917 if d.Name() != "android.car-system-stubs-docs" &&
918 d.Name() != "android.car-stubs-docs" {
919 cmd.Flag("--lints-as-errors")
920 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
921 }
922
923 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000924 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
925 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700926
927 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700928 //
929 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
930 // message and metalava's one?
931 msg := `$'` + // Enclose with $' ... '
932 `************************************************************\n` +
933 `Your API changes are triggering API Lint warnings or errors.\n` +
934 `To make these errors go away, fix the code according to the\n` +
935 `error and/or warning messages above.\n` +
936 `\n` +
937 `If it is not possible to do so, there are workarounds:\n` +
938 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000939 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
940 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700941
942 if baselineFile.Valid() {
943 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
944 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
945
946 msg += fmt.Sprintf(``+
947 `2. You can update the baseline by executing the following\n`+
948 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700949 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
950 ` "%s" \\\n`+
951 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700952 ` To submit the revised baseline.txt to the main Android\n`+
953 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
954 } else {
955 msg += fmt.Sprintf(``+
956 `2. You can add a baseline file of existing lint failures\n`+
957 ` to the build rule of %s.\n`, d.Name())
958 }
959 // Note the message ends with a ' (single quote), to close the $' ... ' .
960 msg += `************************************************************\n'`
961
962 cmd.FlagWithArg("--error-message:api-lint ", msg)
963 }
964
965 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000966 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700967 if len(d.Javadoc.properties.Out) > 0 {
968 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
969 }
970
971 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
972 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
973 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000974 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700975
Jihoon Kang3c89f042023-12-19 02:40:22 +0000976 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700977
978 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
979 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
980
981 if baselineFile.Valid() {
982 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
983 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
984 }
985
986 // Note this string includes quote ($' ... '), which decodes the "\n"s.
987 msg := `$'\n******************************\n` +
988 `You have tried to change the API from what has been previously released in\n` +
989 `an SDK. Please fix the errors listed above.\n` +
990 `******************************\n'`
991
992 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
993 }
994
Paul Duffin10a23c22023-08-11 22:47:31 +0100995 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
996 // Pass the current API file into metalava so it can use it as the basis for determining how to
997 // generate the output signature files (both api and removed).
998 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
999 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1000 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001001}
Paul Duffin10a23c22023-08-11 22:47:31 +01001002
Jihoon Kang3c89f042023-12-19 02:40:22 +00001003// Sandbox rule for generating exportable stubs and other artifacts
1004func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1005 optionalCmdParams := stubsCommandParams{
1006 stubConfig: params,
1007 }
1008
1009 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1010 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1011 if params.writeSdkValues {
1012 d.exportableMetadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1013 d.exportableMetadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1014 optionalCmdParams.metadataZip = d.exportableMetadataZip
1015 optionalCmdParams.metadataDir = d.exportableMetadataDir
1016 }
1017
1018 if Bool(d.properties.Annotations_enabled) {
1019 if params.validatingNullability {
1020 d.exportableNullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1021 optionalCmdParams.nullabilityWarningsFile = d.exportableNullabilityWarningsFile
1022 }
1023 d.exportableAnnotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1024 optionalCmdParams.annotationsZip = d.exportableAnnotationsZip
1025 }
1026 if Bool(d.properties.Api_levels_annotations_enabled) {
1027 d.exportableApiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1028 optionalCmdParams.apiVersionsXml = d.exportableApiVersionsXml
1029 }
1030
1031 if params.checkApi || String(d.properties.Api_filename) != "" {
1032 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1033 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1034 }
1035
1036 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1037 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1038 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1039 }
1040
1041 d.optionalStubCmd(ctx, optionalCmdParams)
1042}
1043
1044func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1045
1046 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1047 rule := android.NewRuleBuilder(pctx, ctx)
1048 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1049 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1050 SandboxInputs()
1051
1052 if params.stubConfig.generateStubs {
1053 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1054 }
1055
1056 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1057
1058 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1059
1060 if params.stubConfig.doApiLint {
1061 // Pass the lint baseline file as an input to resolve the lint errors.
1062 // The exportable stubs generation does not update the lint baseline file.
1063 // Lint baseline file update is handled by the everything stubs
1064 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1065 if baselineFile.Valid() {
1066 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1067 }
1068 }
1069
1070 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001071 rule.Command().
1072 BuiltTool("soong_zip").
1073 Flag("-write_if_changed").
1074 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001075 FlagWithOutput("-o ", params.stubsSrcJar).
1076 FlagWithArg("-C ", params.stubsDir.String()).
1077 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001078 }
1079
Jihoon Kang3c89f042023-12-19 02:40:22 +00001080 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001081 rule.Command().
1082 BuiltTool("soong_zip").
1083 Flag("-write_if_changed").
1084 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001085 FlagWithOutput("-o ", params.metadataZip).
1086 FlagWithArg("-C ", params.metadataDir.String()).
1087 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001088 }
1089
Colin Cross6aa5c402021-03-24 12:28:50 -07001090 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001091 if !metalavaUseRbe(ctx) {
1092 rule.Restat()
1093 }
Colin Cross2207f872021-03-24 12:39:08 -07001094
Jihoon Kang3c89f042023-12-19 02:40:22 +00001095 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001096
Jihoon Kang3c89f042023-12-19 02:40:22 +00001097 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1098}
1099
1100func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1101 deps := d.Javadoc.collectDeps(ctx)
1102
1103 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1104 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1105
1106 // Add options for the other optional tasks: API-lint and check-released.
1107 // We generate separate timestamp files for them.
1108 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1109 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1110
1111 writeSdkValues := Bool(d.properties.Write_sdk_values)
1112
1113 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1114
1115 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1116 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1117 String(d.properties.Validate_nullability_from_list) != "")
1118
1119 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1120 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1121
1122 stubCmdParams := stubsCommandConfigParams{
1123 javaVersion: javaVersion,
1124 deps: deps,
1125 checkApi: checkApi,
1126 generateStubs: generateStubs,
1127 doApiLint: doApiLint,
1128 doCheckReleased: doCheckReleased,
1129 writeSdkValues: writeSdkValues,
1130 migratingNullability: migratingNullability,
1131 validatingNullability: validatingNullability,
1132 }
1133 stubCmdParams.stubsType = Everything
1134 // Create default (i.e. "everything" stubs) rule for metalava
1135 d.everythingStubCmd(ctx, stubCmdParams)
1136
1137 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
1138 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1139 // strips all flagged apis to generate the "exportable" stubs
1140 stubCmdParams.stubsType = Exportable
1141 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001142
Paul Duffine7a86642022-08-16 15:43:20 +00001143 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1144
1145 if len(d.Javadoc.properties.Out) > 0 {
1146 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1147 }
1148
1149 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1150 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1151 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1152
1153 if baselineFile.Valid() {
1154 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1155 }
1156
Jihoon Kang3c89f042023-12-19 02:40:22 +00001157 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001158
1159 rule := android.NewRuleBuilder(pctx, ctx)
1160
1161 // Diff command line.
1162 // -F matches the closest "opening" line, such as "package android {"
1163 // and " public class Intent {".
1164 diff := `diff -u -F '{ *$'`
1165
1166 rule.Command().Text("( true")
1167 rule.Command().
1168 Text(diff).
1169 Input(apiFile).Input(d.apiFile)
1170
1171 rule.Command().
1172 Text(diff).
1173 Input(removedApiFile).Input(d.removedApiFile)
1174
1175 msg := fmt.Sprintf(`\n******************************\n`+
1176 `You have tried to change the API from what has been previously approved.\n\n`+
1177 `To make these errors go away, you have two choices:\n`+
1178 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1179 ` to the new methods, etc. shown in the above diff.\n\n`+
1180 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1181 ` m %s-update-current-api\n\n`+
1182 ` To submit the revised current.txt to the main Android repository,\n`+
1183 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001184 `If your build failed due to stub validation, you can resolve the errors with\n`+
1185 `either of the two choices above and try re-building the target.\n`+
1186 `If the mismatch between the stubs and the current.txt is intended,\n`+
1187 `you can try re-building the target by executing the following command:\n`+
1188 `m DISABLE_STUB_VALIDATION=true <your build target>\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001189 `******************************\n`, ctx.ModuleName())
1190
1191 rule.Command().
1192 Text("touch").Output(d.checkCurrentApiTimestamp).
1193 Text(") || (").
1194 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1195 Text("; exit 38").
1196 Text(")")
1197
1198 rule.Build("metalavaCurrentApiCheck", "check current API")
1199
Jihoon Kang3c89f042023-12-19 02:40:22 +00001200 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001201
1202 // update API rule
1203 rule = android.NewRuleBuilder(pctx, ctx)
1204
1205 rule.Command().Text("( true")
1206
1207 rule.Command().
1208 Text("cp").Flag("-f").
1209 Input(d.apiFile).Flag(apiFile.String())
1210
1211 rule.Command().
1212 Text("cp").Flag("-f").
1213 Input(d.removedApiFile).Flag(removedApiFile.String())
1214
1215 msg = "failed to update public API"
1216
1217 rule.Command().
1218 Text("touch").Output(d.updateCurrentApiTimestamp).
1219 Text(") || (").
1220 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1221 Text("; exit 38").
1222 Text(")")
1223
1224 rule.Build("metalavaCurrentApiUpdate", "update current API")
1225 }
1226
Colin Cross2207f872021-03-24 12:39:08 -07001227 if String(d.properties.Check_nullability_warnings) != "" {
1228 if d.nullabilityWarningsFile == nil {
1229 ctx.PropertyErrorf("check_nullability_warnings",
1230 "Cannot specify check_nullability_warnings unless validating nullability")
1231 }
1232
1233 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1234
Jihoon Kang3c89f042023-12-19 02:40:22 +00001235 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001236
1237 msg := fmt.Sprintf(`\n******************************\n`+
1238 `The warnings encountered during nullability annotation validation did\n`+
1239 `not match the checked in file of expected warnings. The diffs are shown\n`+
1240 `above. You have two options:\n`+
1241 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1242 ` 2. Update the file of expected warnings by running:\n`+
1243 ` cp %s %s\n`+
1244 ` and submitting the updated file as part of your change.`,
1245 d.nullabilityWarningsFile, checkNullabilityWarnings)
1246
1247 rule := android.NewRuleBuilder(pctx, ctx)
1248
1249 rule.Command().
1250 Text("(").
1251 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
1252 Text("&&").
1253 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1254 Text(") || (").
1255 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1256 Text("; exit 38").
1257 Text(")")
1258
1259 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1260 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001261 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001262}
1263
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001264func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1265 api_file := d.properties.Check_api.Current.Api_file
1266 api_surface := d.properties.Api_surface
1267
1268 props := struct {
1269 Name *string
1270 Api_surface *string
1271 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001272 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001273 }{}
1274
1275 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1276 props.Api_surface = api_surface
1277 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001278 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001279
1280 ctx.CreateModule(ApiContributionFactory, &props)
1281}
1282
Spandan Das0b555e32022-11-28 18:48:51 +00001283// TODO (b/262014796): Export the API contributions of CorePlatformApi
1284// A map to populate the api surface of a droidstub from a substring appearing in its name
1285// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1286// use a strict naming convention
1287var (
1288 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1289 //public is commented out since the core libraries use public in their java_sdk_library names
1290 "intracore": android.SdkIntraCore,
1291 "intra.core": android.SdkIntraCore,
1292 "system_server": android.SdkSystemServer,
1293 "system-server": android.SdkSystemServer,
1294 "system": android.SdkSystem,
1295 "module_lib": android.SdkModule,
1296 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001297 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001298 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001299 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001300 }
1301)
1302
Colin Cross2207f872021-03-24 12:39:08 -07001303func StubsDefaultsFactory() android.Module {
1304 module := &DocDefaults{}
1305
1306 module.AddProperties(
1307 &JavadocProperties{},
1308 &DroidstubsProperties{},
1309 )
1310
1311 android.InitDefaultsModule(module)
1312
1313 return module
1314}
1315
1316var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1317
1318type PrebuiltStubsSourcesProperties struct {
1319 Srcs []string `android:"path"`
1320}
1321
1322type PrebuiltStubsSources struct {
1323 android.ModuleBase
1324 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001325 embeddableInModuleAndImport
1326
Colin Cross2207f872021-03-24 12:39:08 -07001327 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001328
1329 properties PrebuiltStubsSourcesProperties
1330
kgui67007242022-01-25 13:50:25 +08001331 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001332}
1333
1334func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1335 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001336 // prebuilt droidstubs does not output "exportable" stubs.
1337 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1338 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001339 return android.Paths{p.stubsSrcJar}, nil
1340 default:
1341 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1342 }
1343}
1344
1345func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
1346 return d.stubsSrcJar
1347}
1348
1349func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001350 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001351 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 -07001352 return
1353 }
1354
Anton Hansson86758ac2021-11-03 14:44:12 +00001355 src := p.properties.Srcs[0]
1356 if filepath.Ext(src) == ".srcjar" {
1357 // This is a srcjar. We can use it directly.
1358 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1359 } else {
1360 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001361
Anton Hansson86758ac2021-11-03 14:44:12 +00001362 // This is a directory. Glob the contents just in case the directory does not exist.
1363 srcGlob := src + "/**/*"
1364 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001365
Anton Hansson86758ac2021-11-03 14:44:12 +00001366 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1367 // the path components are invalid it won't in this case because no components
1368 // are specified and the module directory must exist in order to get this far.
1369 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001370
Anton Hansson86758ac2021-11-03 14:44:12 +00001371 rule := android.NewRuleBuilder(pctx, ctx)
1372 rule.Command().
1373 BuiltTool("soong_zip").
1374 Flag("-write_if_changed").
1375 Flag("-jar").
1376 FlagWithOutput("-o ", outPath).
1377 FlagWithArg("-C ", srcDir.String()).
1378 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1379 rule.Restat()
1380 rule.Build("zip src", "Create srcjar from prebuilt source")
1381 p.stubsSrcJar = outPath
1382 }
Colin Cross2207f872021-03-24 12:39:08 -07001383}
1384
1385func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1386 return &p.prebuilt
1387}
1388
1389func (p *PrebuiltStubsSources) Name() string {
1390 return p.prebuilt.Name(p.ModuleBase.Name())
1391}
1392
1393// prebuilt_stubs_sources imports a set of java source files as if they were
1394// generated by droidstubs.
1395//
1396// By default, a prebuilt_stubs_sources has a single variant that expects a
1397// set of `.java` files generated by droidstubs.
1398//
1399// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1400// for host modules.
1401//
1402// Intended only for use by sdk snapshots.
1403func PrebuiltStubsSourcesFactory() android.Module {
1404 module := &PrebuiltStubsSources{}
1405
1406 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001407 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001408
1409 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001410 InitDroiddocModule(module, android.HostAndDeviceSupported)
1411 return module
1412}