blob: ef1398894feb1dba07c717277b51b2533a9d18b7 [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
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000199type ExportableApiStubsSrcProvider interface {
200 ExportableStubsSrcJar() android.Path
201}
202
Anton Hansson52609322021-05-05 10:36:05 +0100203// Provider of information about API stubs, used by java_sdk_library.
204type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100205 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100206 ApiFilePath
207 RemovedApiFilePath() android.Path
208
209 ApiStubsSrcProvider
210}
211
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000212type ExportableApiStubsProvider interface {
213 ExportableAnnotationsZip() android.Path
214 ExportableApiFilePath() android.Path
215 ExportableRemovedApiFilePath() android.Path
216
217 ExportableApiStubsSrcProvider
218}
219
Jihoon Kang063ec002023-06-28 01:16:23 +0000220type currentApiTimestampProvider interface {
221 CurrentApiTimestamp() android.Path
222}
223
Jihoon Kang3c89f042023-12-19 02:40:22 +0000224type annotationFlagsParams struct {
225 migratingNullability bool
226 validatingNullability bool
227 nullabilityWarningsFile android.WritablePath
228 annotationsZip android.WritablePath
229}
230type stubsCommandParams struct {
231 srcJarDir android.ModuleOutPath
232 stubsDir android.OptionalPath
233 stubsSrcJar android.WritablePath
234 metadataZip android.WritablePath
235 metadataDir android.WritablePath
236 apiVersionsXml android.WritablePath
237 nullabilityWarningsFile android.WritablePath
238 annotationsZip android.WritablePath
239 stubConfig stubsCommandConfigParams
240}
241type stubsCommandConfigParams struct {
242 stubsType StubsType
243 javaVersion javaVersion
244 deps deps
245 checkApi bool
246 generateStubs bool
247 doApiLint bool
248 doCheckReleased bool
249 writeSdkValues bool
250 migratingNullability bool
251 validatingNullability bool
252}
253
Colin Cross2207f872021-03-24 12:39:08 -0700254// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
255// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
256// a droiddoc module to generate documentation.
257func DroidstubsFactory() android.Module {
258 module := &Droidstubs{}
259
260 module.AddProperties(&module.properties,
261 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000262 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700263
264 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000265
266 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
267 module.createApiContribution(ctx)
268 })
Colin Cross2207f872021-03-24 12:39:08 -0700269 return module
270}
271
272// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
273// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
274// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
275// module when symbols needed by the source files are provided by java_library_host modules.
276func DroidstubsHostFactory() android.Module {
277 module := &Droidstubs{}
278
279 module.AddProperties(&module.properties,
280 &module.Javadoc.properties)
281
282 InitDroiddocModule(module, android.HostSupported)
283 return module
284}
285
Jihoon Kang78f89142023-12-27 01:40:29 +0000286func getStubsTypeAndTag(tag string) (StubsType, string, error) {
287 if len(tag) == 0 {
288 return Everything, "", nil
289 }
290 if tag[0] != '.' {
291 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
292 }
293
294 stubsType := Everything
295 // Check if the tag has a stubs type prefix (e.g. ".exportable")
296 for st := Everything; st <= Exportable; st++ {
297 if strings.HasPrefix(tag, "."+st.String()) {
298 stubsType = st
299 }
300 }
301
302 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
303}
304
305// Droidstubs' tag supports specifying with the stubs type.
306// While supporting the pre-existing tags, it also supports tags with
307// the stubs type prefix. Some examples are shown below:
308// {.annotations.zip} - pre-existing behavior. Returns the path to the
309// annotation zip.
310// {.exportable} - Returns the path to the exportable stubs src jar.
311// {.exportable.annotations.zip} - Returns the path to the exportable
312// annotations zip file.
313// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
314// xml file. For unsupported combinations, the default everything output file
315// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700316func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000317 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
318 if err != nil {
319 return nil, err
320 }
321 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700322 case "":
Jihoon Kang78f89142023-12-27 01:40:29 +0000323 return d.StubsSrcJarWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700324 case ".docs.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000325 return d.DocZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700326 case ".api.txt", android.DefaultDistTag:
327 // This is the default dist path for dist properties that have no tag property.
Jihoon Kang78f89142023-12-27 01:40:29 +0000328 return d.ApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700329 case ".removed-api.txt":
Jihoon Kang78f89142023-12-27 01:40:29 +0000330 return d.RemovedApiFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700331 case ".annotations.zip":
Jihoon Kang78f89142023-12-27 01:40:29 +0000332 return d.AnnotationsZipWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700333 case ".api_versions.xml":
Jihoon Kang78f89142023-12-27 01:40:29 +0000334 return d.ApiVersionsXmlFilePathWithStubsType(stubsType)
Colin Cross2207f872021-03-24 12:39:08 -0700335 default:
336 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
337 }
338}
339
Anton Hanssond78eb762021-09-21 15:25:12 +0100340func (d *Droidstubs) AnnotationsZip() android.Path {
341 return d.annotationsZip
342}
343
Jihoon Kang78f89142023-12-27 01:40:29 +0000344func (d *Droidstubs) ExportableAnnotationsZip() android.Path {
345 return d.exportableAnnotationsZip
346}
347
348func (d *Droidstubs) AnnotationsZipWithStubsType(stubsType StubsType) (android.Paths, error) {
349 switch stubsType {
350 case Everything:
351 return android.Paths{d.AnnotationsZip()}, nil
352 case Exportable:
353 return android.Paths{d.ExportableAnnotationsZip()}, nil
354 default:
355 return nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
356 }
357}
358
Colin Cross2207f872021-03-24 12:39:08 -0700359func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000360 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700361}
362
Jihoon Kang78f89142023-12-27 01:40:29 +0000363func (d *Droidstubs) ExportableApiFilePath() android.Path {
364 return d.exportableApiFile
365}
366
367func (d *Droidstubs) ApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
368 switch stubsType {
369 case Everything:
370 return android.Paths{d.ApiFilePath()}, nil
371 case Exportable:
372 return android.Paths{d.ExportableApiFilePath()}, nil
373 default:
374 return nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
375 }
376}
377
378func (d *Droidstubs) ApiVersionsXmlFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
379 switch stubsType {
380 case Everything:
381 return android.Paths{d.apiVersionsXml}, nil
382 default:
383 return nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
384 }
385}
386
387func (d *Droidstubs) DocZipWithStubsType(stubsType StubsType) (android.Paths, error) {
388 switch stubsType {
389 case Everything:
390 return android.Paths{d.docZip}, nil
391 default:
392 return nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
393 }
394}
395
Colin Cross2207f872021-03-24 12:39:08 -0700396func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000397 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700398}
399
Jihoon Kang78f89142023-12-27 01:40:29 +0000400func (d *Droidstubs) ExportableRemovedApiFilePath() android.Path {
401 return d.exportableRemovedApiFile
402}
403
404func (d *Droidstubs) RemovedApiFilePathWithStubsType(stubsType StubsType) (android.Paths, error) {
405 switch stubsType {
406 case Everything:
407 return android.Paths{d.RemovedApiFilePath()}, nil
408 case Exportable:
409 return android.Paths{d.ExportableRemovedApiFilePath()}, nil
410 default:
411 return nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
412 }
413}
414
Colin Cross2207f872021-03-24 12:39:08 -0700415func (d *Droidstubs) StubsSrcJar() android.Path {
416 return d.stubsSrcJar
417}
418
Jihoon Kang78f89142023-12-27 01:40:29 +0000419func (d *Droidstubs) ExportableStubsSrcJar() android.Path {
420 return d.exportableStubsSrcJar
421}
422
423func (d *Droidstubs) StubsSrcJarWithStubsType(stubsType StubsType) (android.Paths, error) {
424 switch stubsType {
425 case Everything:
426 return android.Paths{d.StubsSrcJar()}, nil
427 case Exportable:
428 return android.Paths{d.ExportableStubsSrcJar()}, nil
429 default:
430 return nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
431 }
432}
433
Jihoon Kang063ec002023-06-28 01:16:23 +0000434func (d *Droidstubs) CurrentApiTimestamp() android.Path {
435 return d.checkCurrentApiTimestamp
436}
437
Colin Cross2207f872021-03-24 12:39:08 -0700438var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
439var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
440var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000441var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000442var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700443
444func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
445 d.Javadoc.addDeps(ctx)
446
447 if len(d.properties.Merge_annotations_dirs) != 0 {
448 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
449 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
450 }
451 }
452
453 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
454 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
455 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
456 }
457 }
458
459 if len(d.properties.Api_levels_annotations_dirs) != 0 {
460 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
461 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
462 }
463 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000464
Jihoon Kang6592e872023-12-19 01:13:16 +0000465 if len(d.properties.Aconfig_declarations) != 0 {
466 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
467 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
468 }
469 }
470
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000471 if d.properties.Api_levels_module != nil {
472 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
473 }
Colin Cross2207f872021-03-24 12:39:08 -0700474}
475
Jihoon Kang3c89f042023-12-19 02:40:22 +0000476func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
477 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
478}
479
480func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
481 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700482 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000483 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000484 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000485
486 if stubsType == Everything {
487 d.apiFile = uncheckedApiFile
488 } else if stubsType == Exportable {
489 d.exportableApiFile = uncheckedApiFile
490 }
Colin Cross2207f872021-03-24 12:39:08 -0700491 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
492 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000493 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700494 }
495
Jihoon Kang3c89f042023-12-19 02:40:22 +0000496 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700497 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000498 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000499 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000500
501 if stubsType == Everything {
502 d.removedApiFile = uncheckedRemovedFile
503 } else if stubsType == Exportable {
504 d.exportableRemovedApiFile = uncheckedRemovedFile
505 }
Colin Cross2207f872021-03-24 12:39:08 -0700506 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
507 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000508 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700509 }
510
Colin Cross2207f872021-03-24 12:39:08 -0700511 if stubsDir.Valid() {
512 if Bool(d.properties.Create_doc_stubs) {
513 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
514 } else {
515 cmd.FlagWithArg("--stubs ", stubsDir.String())
516 if !Bool(d.properties.Output_javadoc_comments) {
517 cmd.Flag("--exclude-documentation-from-stubs")
518 }
519 }
520 }
521}
522
Jihoon Kang3c89f042023-12-19 02:40:22 +0000523func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Colin Cross2207f872021-03-24 12:39:08 -0700524 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400525 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100526
Jihoon Kang3c89f042023-12-19 02:40:22 +0000527 if params.migratingNullability {
Colin Cross2207f872021-03-24 12:39:08 -0700528 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
529 cmd.FlagWithInput("--migrate-nullness ", previousApi)
530 }
531
532 if s := String(d.properties.Validate_nullability_from_list); s != "" {
533 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
534 }
535
Jihoon Kang3c89f042023-12-19 02:40:22 +0000536 if params.validatingNullability {
537 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
Colin Cross2207f872021-03-24 12:39:08 -0700538 }
539
Jihoon Kang3c89f042023-12-19 02:40:22 +0000540 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Colin Cross2207f872021-03-24 12:39:08 -0700541
542 if len(d.properties.Merge_annotations_dirs) != 0 {
543 d.mergeAnnoDirFlags(ctx, cmd)
544 }
545
Liz Kammere09e20e2023-10-16 15:07:54 -0400546 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700547 }
548}
549
550func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
551 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
552 if t, ok := m.(*ExportedDroiddocDir); ok {
553 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
554 } else {
555 ctx.PropertyErrorf("merge_annotations_dirs",
556 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
557 }
558 })
559}
560
561func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
562 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
563 if t, ok := m.(*ExportedDroiddocDir); ok {
564 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
565 } else {
566 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
567 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
568 }
569 })
570}
571
Jihoon Kang3c89f042023-12-19 02:40:22 +0000572func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000573 var apiVersions android.Path
574 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000575 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000576 apiVersions = d.apiVersionsXml
577 } else {
578 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
579 if s, ok := m.(*Droidstubs); ok {
580 apiVersions = s.apiVersionsXml
581 } else {
582 ctx.PropertyErrorf("api_levels_module",
583 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
584 }
585 })
Colin Cross2207f872021-03-24 12:39:08 -0700586 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000587 if apiVersions != nil {
588 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
589 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
590 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
591 }
592}
Colin Cross2207f872021-03-24 12:39:08 -0700593
Jihoon Kang3c89f042023-12-19 02:40:22 +0000594func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700595 if len(d.properties.Api_levels_annotations_dirs) == 0 {
596 ctx.PropertyErrorf("api_levels_annotations_dirs",
597 "has to be non-empty if api levels annotations was enabled!")
598 }
599
Jihoon Kang3c89f042023-12-19 02:40:22 +0000600 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700601
602 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
603
satayev783195c2021-06-23 21:49:57 +0100604 var dirs []string
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200605 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700606 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
607 if t, ok := m.(*ExportedDroiddocDir); ok {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200608 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
609
610 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
611 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700612 for _, dep := range t.deps {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200613 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
614 if extensions_dir == "" {
615 extensions_dir = t.dir.String() + "/extensions"
616 }
617 cmd.Implicit(dep)
618 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700619 if dep.Base() == filename {
620 cmd.Implicit(dep)
621 }
622 if filename != "android.jar" && dep.Base() == "android.jar" {
623 // Metalava implicitly searches these patterns:
624 // prebuilts/tools/common/api-versions/android-%/android.jar
625 // prebuilts/sdk/%/public/android.jar
626 // Add android.jar files from the api_levels_annotations_dirs directories to try
627 // to satisfy these patterns. If Metalava can't find a match for an API level
628 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700629 cmd.Implicit(dep)
630 }
631 }
satayev783195c2021-06-23 21:49:57 +0100632
633 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700634 } else {
635 ctx.PropertyErrorf("api_levels_annotations_dirs",
636 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
637 }
638 })
satayev783195c2021-06-23 21:49:57 +0100639
640 // Add all relevant --android-jar-pattern patterns for Metalava.
641 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
642 // an actual file present on disk (in the order the patterns were passed). For system APIs for
643 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000644 // for older releases. Similarly, module-lib falls back to system API.
645 var sdkDirs []string
646 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700647 case "system-server":
648 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000649 case "module-lib":
650 sdkDirs = []string{"module-lib", "system", "public"}
651 case "system":
652 sdkDirs = []string{"system", "public"}
653 case "public":
654 sdkDirs = []string{"public"}
655 default:
656 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
657 return
satayev783195c2021-06-23 21:49:57 +0100658 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000659
660 for _, sdkDir := range sdkDirs {
661 for _, dir := range dirs {
662 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
663 }
satayev783195c2021-06-23 21:49:57 +0100664 }
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200665
666 if d.properties.Extensions_info_file != nil {
667 if extensions_dir == "" {
668 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
669 }
670 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
671 cmd.Implicit(info_file)
672 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
673 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
674 }
Colin Cross2207f872021-03-24 12:39:08 -0700675}
676
Colin Crosse52c2ac2022-03-28 17:03:35 -0700677func metalavaUseRbe(ctx android.ModuleContext) bool {
678 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
679}
680
Colin Cross2207f872021-03-24 12:39:08 -0700681func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100682 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700683 rule.Command().Text("rm -rf").Flag(homeDir.String())
684 rule.Command().Text("mkdir -p").Flag(homeDir.String())
685
Anton Hansson556e8142021-06-04 16:20:25 +0100686 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700687 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
688
Colin Crosse52c2ac2022-03-28 17:03:35 -0700689 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700690 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700691 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000692 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
693 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700694 labels := map[string]string{"type": "tool", "name": "metalava"}
695 // TODO: metalava pool rejects these jobs
696 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
697 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000698 Labels: labels,
699 ExecStrategy: execStrategy,
700 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
701 Platform: map[string]string{remoteexec.PoolKey: pool},
702 Compare: compare,
703 NumLocalRuns: 1,
704 NumRemoteRuns: 1,
705 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700706 })
Colin Cross2207f872021-03-24 12:39:08 -0700707 }
708
Colin Cross6aa5c402021-03-24 12:28:50 -0700709 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700710 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400711 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100712 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700713 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
714 FlagWithInput("@", srcJarList)
715
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100716 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
717 // years, so it is unlikely to change any time soon.
718 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
719 combinedPaths = append(combinedPaths, classpath.Paths()...)
720 if len(combinedPaths) > 0 {
721 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700722 }
723
Liz Kammere09e20e2023-10-16 15:07:54 -0400724 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000725 if ctx.DeviceConfig().HideFlaggedApis() {
Liz Kammere09e20e2023-10-16 15:07:54 -0400726 cmd.Flag(config.MetalavaHideFlaggedApis)
Jihoon Kangc8313892023-09-20 00:54:47 +0000727 }
728
Colin Cross2207f872021-03-24 12:39:08 -0700729 return cmd
730}
731
Jihoon Kang3c89f042023-12-19 02:40:22 +0000732// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
733// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
734// property is defined, apply transformations and only revert the flagged apis that are not
735// enabled via release configurations and are not specified in aconfig_declarations
736func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
737
738 if len(aconfigFlagsPaths) == 0 {
739 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
740 return
741 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000742
743 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
744 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
745
746 var filterArgs string
747 switch stubsType {
748 // No flagged apis specific flags need to be passed to metalava when generating
749 // everything stubs
750 case Everything:
751 return
752
753 case Runtime:
754 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
755
756 case Exportable:
757 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
758
759 }
760
761 ctx.Build(pctx, android.BuildParams{
762 Rule: gatherReleasedFlaggedApisRule,
763 Inputs: aconfigFlagsPaths,
764 Output: releasedFlaggedApisFile,
765 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
766 Args: map[string]string{
767 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
768 "filter_args": filterArgs,
769 },
770 })
771
772 ctx.Build(pctx, android.BuildParams{
773 Rule: generateMetalavaRevertAnnotationsRule,
774 Input: releasedFlaggedApisFile,
775 Output: revertAnnotationsFile,
776 Description: fmt.Sprintf("%s revert annotations", stubsType),
777 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000778
779 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000780}
781
Jihoon Kang3c89f042023-12-19 02:40:22 +0000782func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
783 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700784 if BoolDefault(d.properties.High_mem, false) {
785 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
786 rule.HighMem()
787 }
788
Jihoon Kang3c89f042023-12-19 02:40:22 +0000789 if params.stubConfig.generateStubs {
790 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
791 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700792 }
793
Jihoon Kang3c89f042023-12-19 02:40:22 +0000794 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700795
Jihoon Kang3c89f042023-12-19 02:40:22 +0000796 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
797 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
798 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700799 cmd.Implicits(d.Javadoc.implicits)
800
Jihoon Kang3c89f042023-12-19 02:40:22 +0000801 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700802
Jihoon Kang3c89f042023-12-19 02:40:22 +0000803 if params.stubConfig.writeSdkValues {
804 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
805 }
806
807 annotationParams := annotationFlagsParams{
808 migratingNullability: params.stubConfig.migratingNullability,
809 validatingNullability: params.stubConfig.validatingNullability,
810 nullabilityWarningsFile: params.nullabilityWarningsFile,
811 annotationsZip: params.annotationsZip,
812 }
813
814 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700815 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000816 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700817
Colin Crossbc139922021-03-25 18:33:16 -0700818 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700819
Colin Cross2207f872021-03-24 12:39:08 -0700820 for _, o := range d.Javadoc.properties.Out {
821 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
822 }
823
Jihoon Kang3c89f042023-12-19 02:40:22 +0000824 return cmd
825}
Colin Cross2207f872021-03-24 12:39:08 -0700826
Jihoon Kang3c89f042023-12-19 02:40:22 +0000827// Sandbox rule for generating the everything stubs and other artifacts
828func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
829 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
830 rule := android.NewRuleBuilder(pctx, ctx)
831 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
832 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
833 SandboxInputs()
834
835 var stubsDir android.OptionalPath
836 if params.generateStubs {
837 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
838 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
839 }
840
841 if params.writeSdkValues {
842 d.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
843 d.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
844 }
845
846 if Bool(d.properties.Annotations_enabled) {
847 if params.validatingNullability {
848 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
849 }
850 d.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
851 }
852 if Bool(d.properties.Api_levels_annotations_enabled) {
853 d.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
854 }
855
856 commonCmdParams := stubsCommandParams{
857 srcJarDir: srcJarDir,
858 stubsDir: stubsDir,
859 stubsSrcJar: d.Javadoc.stubsSrcJar,
860 metadataDir: d.metadataDir,
861 apiVersionsXml: d.apiVersionsXml,
862 nullabilityWarningsFile: d.nullabilityWarningsFile,
863 annotationsZip: d.annotationsZip,
864 stubConfig: params,
865 }
866
867 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
868
869 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
870
871 if params.generateStubs {
872 rule.Command().
873 BuiltTool("soong_zip").
874 Flag("-write_if_changed").
875 Flag("-jar").
876 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
877 FlagWithArg("-C ", stubsDir.String()).
878 FlagWithArg("-D ", stubsDir.String())
879 }
880
881 if params.writeSdkValues {
882 rule.Command().
883 BuiltTool("soong_zip").
884 Flag("-write_if_changed").
885 Flag("-d").
886 FlagWithOutput("-o ", d.metadataZip).
887 FlagWithArg("-C ", d.metadataDir.String()).
888 FlagWithArg("-D ", d.metadataDir.String())
889 }
890
891 // TODO: We don't really need two separate API files, but this is a reminiscence of how
892 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
893 if params.doApiLint {
894 rule.Command().Text("touch").Output(d.apiLintTimestamp)
895 }
896 if params.doCheckReleased {
897 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
898 }
899
900 // TODO(b/183630617): rewrapper doesn't support restat rules
901 if !metalavaUseRbe(ctx) {
902 rule.Restat()
903 }
904
905 zipSyncCleanupCmd(rule, srcJarDir)
906
907 rule.Build("metalava", "metalava merged")
908}
909
910// Sandbox rule for generating the everything artifacts that are not run by
911// default but only run based on the module configurations
912func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700913
914 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000915 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700916 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
917 if newSince.Valid() {
918 cmd.FlagWithInput("--api-lint ", newSince.Path())
919 } else {
920 cmd.Flag("--api-lint")
921 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000922 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700923 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
924
Colin Cross0d532412021-03-25 09:38:45 -0700925 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700926 if d.Name() != "android.car-system-stubs-docs" &&
927 d.Name() != "android.car-stubs-docs" {
928 cmd.Flag("--lints-as-errors")
929 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
930 }
931
932 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000933 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
934 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700935
936 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700937 //
938 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
939 // message and metalava's one?
940 msg := `$'` + // Enclose with $' ... '
941 `************************************************************\n` +
942 `Your API changes are triggering API Lint warnings or errors.\n` +
943 `To make these errors go away, fix the code according to the\n` +
944 `error and/or warning messages above.\n` +
945 `\n` +
946 `If it is not possible to do so, there are workarounds:\n` +
947 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000948 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
949 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700950
951 if baselineFile.Valid() {
952 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
953 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
954
955 msg += fmt.Sprintf(``+
956 `2. You can update the baseline by executing the following\n`+
957 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700958 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
959 ` "%s" \\\n`+
960 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700961 ` To submit the revised baseline.txt to the main Android\n`+
962 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
963 } else {
964 msg += fmt.Sprintf(``+
965 `2. You can add a baseline file of existing lint failures\n`+
966 ` to the build rule of %s.\n`, d.Name())
967 }
968 // Note the message ends with a ' (single quote), to close the $' ... ' .
969 msg += `************************************************************\n'`
970
971 cmd.FlagWithArg("--error-message:api-lint ", msg)
972 }
973
974 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000975 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700976 if len(d.Javadoc.properties.Out) > 0 {
977 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
978 }
979
980 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
981 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
982 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000983 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700984
Jihoon Kang3c89f042023-12-19 02:40:22 +0000985 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700986
987 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
988 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
989
990 if baselineFile.Valid() {
991 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
992 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
993 }
994
995 // Note this string includes quote ($' ... '), which decodes the "\n"s.
996 msg := `$'\n******************************\n` +
997 `You have tried to change the API from what has been previously released in\n` +
998 `an SDK. Please fix the errors listed above.\n` +
999 `******************************\n'`
1000
1001 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1002 }
1003
Paul Duffin10a23c22023-08-11 22:47:31 +01001004 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1005 // Pass the current API file into metalava so it can use it as the basis for determining how to
1006 // generate the output signature files (both api and removed).
1007 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1008 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1009 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001010}
Paul Duffin10a23c22023-08-11 22:47:31 +01001011
Jihoon Kang3c89f042023-12-19 02:40:22 +00001012// Sandbox rule for generating exportable stubs and other artifacts
1013func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1014 optionalCmdParams := stubsCommandParams{
1015 stubConfig: params,
1016 }
1017
1018 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1019 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1020 if params.writeSdkValues {
1021 d.exportableMetadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1022 d.exportableMetadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1023 optionalCmdParams.metadataZip = d.exportableMetadataZip
1024 optionalCmdParams.metadataDir = d.exportableMetadataDir
1025 }
1026
1027 if Bool(d.properties.Annotations_enabled) {
1028 if params.validatingNullability {
1029 d.exportableNullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1030 optionalCmdParams.nullabilityWarningsFile = d.exportableNullabilityWarningsFile
1031 }
1032 d.exportableAnnotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1033 optionalCmdParams.annotationsZip = d.exportableAnnotationsZip
1034 }
1035 if Bool(d.properties.Api_levels_annotations_enabled) {
1036 d.exportableApiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1037 optionalCmdParams.apiVersionsXml = d.exportableApiVersionsXml
1038 }
1039
1040 if params.checkApi || String(d.properties.Api_filename) != "" {
1041 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1042 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1043 }
1044
1045 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1046 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1047 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1048 }
1049
1050 d.optionalStubCmd(ctx, optionalCmdParams)
1051}
1052
1053func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1054
1055 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1056 rule := android.NewRuleBuilder(pctx, ctx)
1057 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1058 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1059 SandboxInputs()
1060
1061 if params.stubConfig.generateStubs {
1062 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1063 }
1064
1065 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1066
1067 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1068
1069 if params.stubConfig.doApiLint {
1070 // Pass the lint baseline file as an input to resolve the lint errors.
1071 // The exportable stubs generation does not update the lint baseline file.
1072 // Lint baseline file update is handled by the everything stubs
1073 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1074 if baselineFile.Valid() {
1075 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1076 }
1077 }
1078
1079 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001080 rule.Command().
1081 BuiltTool("soong_zip").
1082 Flag("-write_if_changed").
1083 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001084 FlagWithOutput("-o ", params.stubsSrcJar).
1085 FlagWithArg("-C ", params.stubsDir.String()).
1086 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001087 }
1088
Jihoon Kang3c89f042023-12-19 02:40:22 +00001089 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001090 rule.Command().
1091 BuiltTool("soong_zip").
1092 Flag("-write_if_changed").
1093 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001094 FlagWithOutput("-o ", params.metadataZip).
1095 FlagWithArg("-C ", params.metadataDir.String()).
1096 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001097 }
1098
Colin Cross6aa5c402021-03-24 12:28:50 -07001099 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001100 if !metalavaUseRbe(ctx) {
1101 rule.Restat()
1102 }
Colin Cross2207f872021-03-24 12:39:08 -07001103
Jihoon Kang3c89f042023-12-19 02:40:22 +00001104 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001105
Jihoon Kang3c89f042023-12-19 02:40:22 +00001106 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1107}
1108
1109func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1110 deps := d.Javadoc.collectDeps(ctx)
1111
1112 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1113 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1114
1115 // Add options for the other optional tasks: API-lint and check-released.
1116 // We generate separate timestamp files for them.
1117 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1118 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1119
1120 writeSdkValues := Bool(d.properties.Write_sdk_values)
1121
1122 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1123
1124 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1125 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1126 String(d.properties.Validate_nullability_from_list) != "")
1127
1128 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1129 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1130
1131 stubCmdParams := stubsCommandConfigParams{
1132 javaVersion: javaVersion,
1133 deps: deps,
1134 checkApi: checkApi,
1135 generateStubs: generateStubs,
1136 doApiLint: doApiLint,
1137 doCheckReleased: doCheckReleased,
1138 writeSdkValues: writeSdkValues,
1139 migratingNullability: migratingNullability,
1140 validatingNullability: validatingNullability,
1141 }
1142 stubCmdParams.stubsType = Everything
1143 // Create default (i.e. "everything" stubs) rule for metalava
1144 d.everythingStubCmd(ctx, stubCmdParams)
1145
1146 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
1147 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1148 // strips all flagged apis to generate the "exportable" stubs
1149 stubCmdParams.stubsType = Exportable
1150 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001151
Paul Duffine7a86642022-08-16 15:43:20 +00001152 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1153
1154 if len(d.Javadoc.properties.Out) > 0 {
1155 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1156 }
1157
1158 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1159 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1160 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1161
1162 if baselineFile.Valid() {
1163 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1164 }
1165
Jihoon Kang3c89f042023-12-19 02:40:22 +00001166 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001167
1168 rule := android.NewRuleBuilder(pctx, ctx)
1169
1170 // Diff command line.
1171 // -F matches the closest "opening" line, such as "package android {"
1172 // and " public class Intent {".
1173 diff := `diff -u -F '{ *$'`
1174
1175 rule.Command().Text("( true")
1176 rule.Command().
1177 Text(diff).
1178 Input(apiFile).Input(d.apiFile)
1179
1180 rule.Command().
1181 Text(diff).
1182 Input(removedApiFile).Input(d.removedApiFile)
1183
1184 msg := fmt.Sprintf(`\n******************************\n`+
1185 `You have tried to change the API from what has been previously approved.\n\n`+
1186 `To make these errors go away, you have two choices:\n`+
1187 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1188 ` to the new methods, etc. shown in the above diff.\n\n`+
1189 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1190 ` m %s-update-current-api\n\n`+
1191 ` To submit the revised current.txt to the main Android repository,\n`+
1192 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001193 `If your build failed due to stub validation, you can resolve the errors with\n`+
1194 `either of the two choices above and try re-building the target.\n`+
1195 `If the mismatch between the stubs and the current.txt is intended,\n`+
1196 `you can try re-building the target by executing the following command:\n`+
1197 `m DISABLE_STUB_VALIDATION=true <your build target>\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001198 `******************************\n`, ctx.ModuleName())
1199
1200 rule.Command().
1201 Text("touch").Output(d.checkCurrentApiTimestamp).
1202 Text(") || (").
1203 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1204 Text("; exit 38").
1205 Text(")")
1206
1207 rule.Build("metalavaCurrentApiCheck", "check current API")
1208
Jihoon Kang3c89f042023-12-19 02:40:22 +00001209 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001210
1211 // update API rule
1212 rule = android.NewRuleBuilder(pctx, ctx)
1213
1214 rule.Command().Text("( true")
1215
1216 rule.Command().
1217 Text("cp").Flag("-f").
1218 Input(d.apiFile).Flag(apiFile.String())
1219
1220 rule.Command().
1221 Text("cp").Flag("-f").
1222 Input(d.removedApiFile).Flag(removedApiFile.String())
1223
1224 msg = "failed to update public API"
1225
1226 rule.Command().
1227 Text("touch").Output(d.updateCurrentApiTimestamp).
1228 Text(") || (").
1229 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1230 Text("; exit 38").
1231 Text(")")
1232
1233 rule.Build("metalavaCurrentApiUpdate", "update current API")
1234 }
1235
Colin Cross2207f872021-03-24 12:39:08 -07001236 if String(d.properties.Check_nullability_warnings) != "" {
1237 if d.nullabilityWarningsFile == nil {
1238 ctx.PropertyErrorf("check_nullability_warnings",
1239 "Cannot specify check_nullability_warnings unless validating nullability")
1240 }
1241
1242 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1243
Jihoon Kang3c89f042023-12-19 02:40:22 +00001244 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001245
1246 msg := fmt.Sprintf(`\n******************************\n`+
1247 `The warnings encountered during nullability annotation validation did\n`+
1248 `not match the checked in file of expected warnings. The diffs are shown\n`+
1249 `above. You have two options:\n`+
1250 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1251 ` 2. Update the file of expected warnings by running:\n`+
1252 ` cp %s %s\n`+
1253 ` and submitting the updated file as part of your change.`,
1254 d.nullabilityWarningsFile, checkNullabilityWarnings)
1255
1256 rule := android.NewRuleBuilder(pctx, ctx)
1257
1258 rule.Command().
1259 Text("(").
1260 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
1261 Text("&&").
1262 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1263 Text(") || (").
1264 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1265 Text("; exit 38").
1266 Text(")")
1267
1268 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1269 }
1270}
1271
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001272func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1273 api_file := d.properties.Check_api.Current.Api_file
1274 api_surface := d.properties.Api_surface
1275
1276 props := struct {
1277 Name *string
1278 Api_surface *string
1279 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001280 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001281 }{}
1282
1283 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1284 props.Api_surface = api_surface
1285 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001286 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001287
1288 ctx.CreateModule(ApiContributionFactory, &props)
1289}
1290
Spandan Das0b555e32022-11-28 18:48:51 +00001291// TODO (b/262014796): Export the API contributions of CorePlatformApi
1292// A map to populate the api surface of a droidstub from a substring appearing in its name
1293// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1294// use a strict naming convention
1295var (
1296 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1297 //public is commented out since the core libraries use public in their java_sdk_library names
1298 "intracore": android.SdkIntraCore,
1299 "intra.core": android.SdkIntraCore,
1300 "system_server": android.SdkSystemServer,
1301 "system-server": android.SdkSystemServer,
1302 "system": android.SdkSystem,
1303 "module_lib": android.SdkModule,
1304 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001305 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001306 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001307 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001308 }
1309)
1310
Colin Cross2207f872021-03-24 12:39:08 -07001311func StubsDefaultsFactory() android.Module {
1312 module := &DocDefaults{}
1313
1314 module.AddProperties(
1315 &JavadocProperties{},
1316 &DroidstubsProperties{},
1317 )
1318
1319 android.InitDefaultsModule(module)
1320
1321 return module
1322}
1323
1324var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1325
1326type PrebuiltStubsSourcesProperties struct {
1327 Srcs []string `android:"path"`
1328}
1329
1330type PrebuiltStubsSources struct {
1331 android.ModuleBase
1332 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001333 embeddableInModuleAndImport
1334
Colin Cross2207f872021-03-24 12:39:08 -07001335 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001336
1337 properties PrebuiltStubsSourcesProperties
1338
kgui67007242022-01-25 13:50:25 +08001339 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001340}
1341
1342func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1343 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001344 // prebuilt droidstubs does not output "exportable" stubs.
1345 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1346 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001347 return android.Paths{p.stubsSrcJar}, nil
1348 default:
1349 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1350 }
1351}
1352
1353func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
1354 return d.stubsSrcJar
1355}
1356
1357func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001358 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001359 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 -07001360 return
1361 }
1362
Anton Hansson86758ac2021-11-03 14:44:12 +00001363 src := p.properties.Srcs[0]
1364 if filepath.Ext(src) == ".srcjar" {
1365 // This is a srcjar. We can use it directly.
1366 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1367 } else {
1368 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001369
Anton Hansson86758ac2021-11-03 14:44:12 +00001370 // This is a directory. Glob the contents just in case the directory does not exist.
1371 srcGlob := src + "/**/*"
1372 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001373
Anton Hansson86758ac2021-11-03 14:44:12 +00001374 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1375 // the path components are invalid it won't in this case because no components
1376 // are specified and the module directory must exist in order to get this far.
1377 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001378
Anton Hansson86758ac2021-11-03 14:44:12 +00001379 rule := android.NewRuleBuilder(pctx, ctx)
1380 rule.Command().
1381 BuiltTool("soong_zip").
1382 Flag("-write_if_changed").
1383 Flag("-jar").
1384 FlagWithOutput("-o ", outPath).
1385 FlagWithArg("-C ", srcDir.String()).
1386 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1387 rule.Restat()
1388 rule.Build("zip src", "Create srcjar from prebuilt source")
1389 p.stubsSrcJar = outPath
1390 }
Colin Cross2207f872021-03-24 12:39:08 -07001391}
1392
1393func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1394 return &p.prebuilt
1395}
1396
1397func (p *PrebuiltStubsSources) Name() string {
1398 return p.prebuilt.Name(p.ModuleBase.Name())
1399}
1400
1401// prebuilt_stubs_sources imports a set of java source files as if they were
1402// generated by droidstubs.
1403//
1404// By default, a prebuilt_stubs_sources has a single variant that expects a
1405// set of `.java` files generated by droidstubs.
1406//
1407// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1408// for host modules.
1409//
1410// Intended only for use by sdk snapshots.
1411func PrebuiltStubsSourcesFactory() android.Module {
1412 module := &PrebuiltStubsSources{}
1413
1414 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001415 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001416
1417 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001418 InitDroiddocModule(module, android.HostAndDeviceSupported)
1419 return module
1420}