blob: 8ab2f2acad950402a6e7c5bd671fe50f9f04e2f8 [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"
Spandan Das0b555e32022-11-28 18:48:51 +000021 "sort"
Colin Cross2207f872021-03-24 12:39:08 -070022 "strings"
23
24 "github.com/google/blueprint/proptools"
25
26 "android/soong/android"
27 "android/soong/java/config"
28 "android/soong/remoteexec"
29)
30
Pedro Loureirocc203502021-10-04 17:24:00 +000031// The values allowed for Droidstubs' Api_levels_sdk_type
Cole Faust051fa912022-10-05 12:45:42 -070032var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
Pedro Loureirocc203502021-10-04 17:24:00 +000033
Colin Cross2207f872021-03-24 12:39:08 -070034func init() {
35 RegisterStubsBuildComponents(android.InitRegistrationContext)
36}
37
38func RegisterStubsBuildComponents(ctx android.RegistrationContext) {
39 ctx.RegisterModuleType("stubs_defaults", StubsDefaultsFactory)
40
41 ctx.RegisterModuleType("droidstubs", DroidstubsFactory)
42 ctx.RegisterModuleType("droidstubs_host", DroidstubsHostFactory)
43
44 ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
45}
46
Colin Cross2207f872021-03-24 12:39:08 -070047// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070048type Droidstubs struct {
49 Javadoc
Colin Cross2207f872021-03-24 12:39:08 -070050
51 properties DroidstubsProperties
Paul Duffinc71d2b72022-08-16 15:24:01 +000052 apiFile android.Path
53 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070054 nullabilityWarningsFile android.WritablePath
55
56 checkCurrentApiTimestamp android.WritablePath
57 updateCurrentApiTimestamp android.WritablePath
58 checkLastReleasedApiTimestamp android.WritablePath
59 apiLintTimestamp android.WritablePath
60 apiLintReport android.WritablePath
61
62 checkNullabilityWarningsTimestamp android.WritablePath
63
64 annotationsZip android.WritablePath
65 apiVersionsXml android.WritablePath
66
Colin Cross2207f872021-03-24 12:39:08 -070067 metadataZip android.WritablePath
68 metadataDir android.WritablePath
69}
70
71type DroidstubsProperties struct {
72 // The generated public API filename by Metalava, defaults to <module>_api.txt
73 Api_filename *string
74
75 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
76 Removed_api_filename *string
77
Colin Cross2207f872021-03-24 12:39:08 -070078 Check_api struct {
79 Last_released ApiToCheck
80
81 Current ApiToCheck
82
83 Api_lint struct {
84 Enabled *bool
85
86 // If set, performs api_lint on any new APIs not found in the given signature file
87 New_since *string `android:"path"`
88
89 // If not blank, path to the baseline txt file for approved API lint violations.
90 Baseline_file *string `android:"path"`
91 }
92 }
93
94 // user can specify the version of previous released API file in order to do compatibility check.
95 Previous_api *string `android:"path"`
96
97 // is set to true, Metalava will allow framework SDK to contain annotations.
98 Annotations_enabled *bool
99
100 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
101 Merge_annotations_dirs []string
102
103 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
104 Merge_inclusion_annotations_dirs []string
105
106 // a file containing a list of classes to do nullability validation for.
107 Validate_nullability_from_list *string
108
109 // a file containing expected warnings produced by validation of nullability annotations.
110 Check_nullability_warnings *string
111
112 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
113 Create_doc_stubs *bool
114
115 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
116 // Has no effect if create_doc_stubs: true.
117 Output_javadoc_comments *bool
118
119 // if set to false then do not write out stubs. Defaults to true.
120 //
121 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
122 Generate_stubs *bool
123
124 // if set to true, provides a hint to the build system that this rule uses a lot of memory,
125 // whicih can be used for scheduling purposes
126 High_mem *bool
127
satayev783195c2021-06-23 21:49:57 +0100128 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700129 Api_levels_annotations_enabled *bool
130
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000131 // Apply the api levels database created by this module rather than generating one in this droidstubs.
132 Api_levels_module *string
133
Colin Cross2207f872021-03-24 12:39:08 -0700134 // the dirs which Metalava extracts API levels annotations from.
135 Api_levels_annotations_dirs []string
136
Cole Faust051fa912022-10-05 12:45:42 -0700137 // 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 +0100138 Api_levels_sdk_type *string
139
Colin Cross2207f872021-03-24 12:39:08 -0700140 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
141 Api_levels_jar_filename *string
142
143 // if set to true, collect the values used by the Dev tools and
144 // write them in files packaged with the SDK. Defaults to false.
145 Write_sdk_values *bool
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200146
147 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
148 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
149 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000150
151 // API surface of this module. If set, the module contributes to an API surface.
152 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
153 Api_surface *string
Colin Cross2207f872021-03-24 12:39:08 -0700154}
155
Anton Hansson52609322021-05-05 10:36:05 +0100156// Used by xsd_config
157type ApiFilePath interface {
158 ApiFilePath() android.Path
159}
160
161type ApiStubsSrcProvider interface {
162 StubsSrcJar() android.Path
163}
164
165// Provider of information about API stubs, used by java_sdk_library.
166type ApiStubsProvider interface {
Anton Hanssond78eb762021-09-21 15:25:12 +0100167 AnnotationsZip() android.Path
Anton Hansson52609322021-05-05 10:36:05 +0100168 ApiFilePath
169 RemovedApiFilePath() android.Path
170
171 ApiStubsSrcProvider
172}
173
Jihoon Kang063ec002023-06-28 01:16:23 +0000174type currentApiTimestampProvider interface {
175 CurrentApiTimestamp() android.Path
176}
177
Colin Cross2207f872021-03-24 12:39:08 -0700178// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
179// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
180// a droiddoc module to generate documentation.
181func DroidstubsFactory() android.Module {
182 module := &Droidstubs{}
183
184 module.AddProperties(&module.properties,
185 &module.Javadoc.properties)
186
187 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000188
189 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
190 module.createApiContribution(ctx)
191 })
Colin Cross2207f872021-03-24 12:39:08 -0700192 return module
193}
194
195// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
196// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
197// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
198// module when symbols needed by the source files are provided by java_library_host modules.
199func DroidstubsHostFactory() android.Module {
200 module := &Droidstubs{}
201
202 module.AddProperties(&module.properties,
203 &module.Javadoc.properties)
204
205 InitDroiddocModule(module, android.HostSupported)
206 return module
207}
208
209func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
210 switch tag {
211 case "":
212 return android.Paths{d.stubsSrcJar}, nil
213 case ".docs.zip":
214 return android.Paths{d.docZip}, nil
215 case ".api.txt", android.DefaultDistTag:
216 // This is the default dist path for dist properties that have no tag property.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000217 return android.Paths{d.apiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700218 case ".removed-api.txt":
Paul Duffinc71d2b72022-08-16 15:24:01 +0000219 return android.Paths{d.removedApiFile}, nil
Colin Cross2207f872021-03-24 12:39:08 -0700220 case ".annotations.zip":
221 return android.Paths{d.annotationsZip}, nil
222 case ".api_versions.xml":
223 return android.Paths{d.apiVersionsXml}, nil
224 default:
225 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
226 }
227}
228
Anton Hanssond78eb762021-09-21 15:25:12 +0100229func (d *Droidstubs) AnnotationsZip() android.Path {
230 return d.annotationsZip
231}
232
Colin Cross2207f872021-03-24 12:39:08 -0700233func (d *Droidstubs) ApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000234 return d.apiFile
Colin Cross2207f872021-03-24 12:39:08 -0700235}
236
237func (d *Droidstubs) RemovedApiFilePath() android.Path {
Paul Duffinc71d2b72022-08-16 15:24:01 +0000238 return d.removedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700239}
240
241func (d *Droidstubs) StubsSrcJar() android.Path {
242 return d.stubsSrcJar
243}
244
Jihoon Kang063ec002023-06-28 01:16:23 +0000245func (d *Droidstubs) CurrentApiTimestamp() android.Path {
246 return d.checkCurrentApiTimestamp
247}
248
Colin Cross2207f872021-03-24 12:39:08 -0700249var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
250var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
251var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000252var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000253var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700254
255func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
256 d.Javadoc.addDeps(ctx)
257
258 if len(d.properties.Merge_annotations_dirs) != 0 {
259 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
260 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
261 }
262 }
263
264 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
265 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
266 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
267 }
268 }
269
270 if len(d.properties.Api_levels_annotations_dirs) != 0 {
271 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
272 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
273 }
274 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000275
276 if d.properties.Api_levels_module != nil {
277 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
278 }
Colin Cross2207f872021-03-24 12:39:08 -0700279}
280
281func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
282 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
283 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
284 String(d.properties.Api_filename) != "" {
285 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Paul Duffinc71d2b72022-08-16 15:24:01 +0000286 uncheckedApiFile := android.PathForModuleOut(ctx, "metalava", filename)
287 cmd.FlagWithOutput("--api ", uncheckedApiFile)
288 d.apiFile = uncheckedApiFile
Colin Cross2207f872021-03-24 12:39:08 -0700289 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
290 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000291 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700292 }
293
294 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
295 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
296 String(d.properties.Removed_api_filename) != "" {
297 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Paul Duffinc71d2b72022-08-16 15:24:01 +0000298 uncheckedRemovedFile := android.PathForModuleOut(ctx, "metalava", filename)
299 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
300 d.removedApiFile = uncheckedRemovedFile
Colin Cross2207f872021-03-24 12:39:08 -0700301 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
302 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000303 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700304 }
305
Colin Cross2207f872021-03-24 12:39:08 -0700306 if Bool(d.properties.Write_sdk_values) {
Colin Crosscb77f752021-03-24 12:04:44 -0700307 d.metadataDir = android.PathForModuleOut(ctx, "metalava", "metadata")
Colin Cross2207f872021-03-24 12:39:08 -0700308 cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
309 }
310
311 if stubsDir.Valid() {
312 if Bool(d.properties.Create_doc_stubs) {
313 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
314 } else {
315 cmd.FlagWithArg("--stubs ", stubsDir.String())
316 if !Bool(d.properties.Output_javadoc_comments) {
317 cmd.Flag("--exclude-documentation-from-stubs")
318 }
319 }
320 }
321}
322
323func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
324 if Bool(d.properties.Annotations_enabled) {
325 cmd.Flag("--include-annotations")
326
Andrei Onea4985e512021-04-29 16:29:34 +0100327 cmd.FlagWithArg("--exclude-annotation ", "androidx.annotation.RequiresApi")
328
Colin Cross2207f872021-03-24 12:39:08 -0700329 validatingNullability :=
Colin Crossbc139922021-03-25 18:33:16 -0700330 strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
Colin Cross2207f872021-03-24 12:39:08 -0700331 String(d.properties.Validate_nullability_from_list) != ""
332
333 migratingNullability := String(d.properties.Previous_api) != ""
334 if migratingNullability {
335 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
336 cmd.FlagWithInput("--migrate-nullness ", previousApi)
337 }
338
339 if s := String(d.properties.Validate_nullability_from_list); s != "" {
340 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
341 }
342
343 if validatingNullability {
Colin Crosscb77f752021-03-24 12:04:44 -0700344 d.nullabilityWarningsFile = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_nullability_warnings.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700345 cmd.FlagWithOutput("--nullability-warnings-txt ", d.nullabilityWarningsFile)
346 }
347
Colin Crosscb77f752021-03-24 12:04:44 -0700348 d.annotationsZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_annotations.zip")
Colin Cross2207f872021-03-24 12:39:08 -0700349 cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
350
351 if len(d.properties.Merge_annotations_dirs) != 0 {
352 d.mergeAnnoDirFlags(ctx, cmd)
353 }
354
355 // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
356 cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
357 FlagWithArg("--hide ", "SuperfluousPrefix").
Sam Gilbert049af112022-03-04 16:03:53 -0500358 FlagWithArg("--hide ", "AnnotationExtraction").
359 // b/222738070
Sam Gilbert675f0b42022-03-08 11:24:44 -0500360 FlagWithArg("--hide ", "BannedThrow").
361 // b/223382732
362 FlagWithArg("--hide ", "ChangedDefault")
Colin Cross2207f872021-03-24 12:39:08 -0700363 }
364}
365
366func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
367 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
368 if t, ok := m.(*ExportedDroiddocDir); ok {
369 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
370 } else {
371 ctx.PropertyErrorf("merge_annotations_dirs",
372 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
373 }
374 })
375}
376
377func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
378 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
379 if t, ok := m.(*ExportedDroiddocDir); ok {
380 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
381 } else {
382 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
383 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
384 }
385 })
386}
387
388func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000389 var apiVersions android.Path
390 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
391 d.apiLevelsGenerationFlags(ctx, cmd)
392 apiVersions = d.apiVersionsXml
393 } else {
394 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
395 if s, ok := m.(*Droidstubs); ok {
396 apiVersions = s.apiVersionsXml
397 } else {
398 ctx.PropertyErrorf("api_levels_module",
399 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
400 }
401 })
Colin Cross2207f872021-03-24 12:39:08 -0700402 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000403 if apiVersions != nil {
404 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
405 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
406 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
407 }
408}
Colin Cross2207f872021-03-24 12:39:08 -0700409
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000410func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
Colin Cross2207f872021-03-24 12:39:08 -0700411 if len(d.properties.Api_levels_annotations_dirs) == 0 {
412 ctx.PropertyErrorf("api_levels_annotations_dirs",
413 "has to be non-empty if api levels annotations was enabled!")
414 }
415
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000416 d.apiVersionsXml = android.PathForModuleOut(ctx, "metalava", "api-versions.xml")
Colin Cross2207f872021-03-24 12:39:08 -0700417 cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700418
419 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
420
satayev783195c2021-06-23 21:49:57 +0100421 var dirs []string
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200422 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700423 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
424 if t, ok := m.(*ExportedDroiddocDir); ok {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200425 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
426
427 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
428 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700429 for _, dep := range t.deps {
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200430 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
431 if extensions_dir == "" {
432 extensions_dir = t.dir.String() + "/extensions"
433 }
434 cmd.Implicit(dep)
435 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700436 if dep.Base() == filename {
437 cmd.Implicit(dep)
438 }
439 if filename != "android.jar" && dep.Base() == "android.jar" {
440 // Metalava implicitly searches these patterns:
441 // prebuilts/tools/common/api-versions/android-%/android.jar
442 // prebuilts/sdk/%/public/android.jar
443 // Add android.jar files from the api_levels_annotations_dirs directories to try
444 // to satisfy these patterns. If Metalava can't find a match for an API level
445 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700446 cmd.Implicit(dep)
447 }
448 }
satayev783195c2021-06-23 21:49:57 +0100449
450 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700451 } else {
452 ctx.PropertyErrorf("api_levels_annotations_dirs",
453 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
454 }
455 })
satayev783195c2021-06-23 21:49:57 +0100456
457 // Add all relevant --android-jar-pattern patterns for Metalava.
458 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
459 // an actual file present on disk (in the order the patterns were passed). For system APIs for
460 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000461 // for older releases. Similarly, module-lib falls back to system API.
462 var sdkDirs []string
463 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700464 case "system-server":
465 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000466 case "module-lib":
467 sdkDirs = []string{"module-lib", "system", "public"}
468 case "system":
469 sdkDirs = []string{"system", "public"}
470 case "public":
471 sdkDirs = []string{"public"}
472 default:
473 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
474 return
satayev783195c2021-06-23 21:49:57 +0100475 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000476
477 for _, sdkDir := range sdkDirs {
478 for _, dir := range dirs {
479 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
480 }
satayev783195c2021-06-23 21:49:57 +0100481 }
Mårten Kongstad802ae0f2022-07-27 13:47:32 +0200482
483 if d.properties.Extensions_info_file != nil {
484 if extensions_dir == "" {
485 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
486 }
487 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
488 cmd.Implicit(info_file)
489 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
490 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
491 }
Colin Cross2207f872021-03-24 12:39:08 -0700492}
493
Colin Crosse52c2ac2022-03-28 17:03:35 -0700494func metalavaUseRbe(ctx android.ModuleContext) bool {
495 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
496}
497
Colin Cross2207f872021-03-24 12:39:08 -0700498func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100499 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700500 rule.Command().Text("rm -rf").Flag(homeDir.String())
501 rule.Command().Text("mkdir -p").Flag(homeDir.String())
502
Anton Hansson556e8142021-06-04 16:20:25 +0100503 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700504 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
505
Colin Crosse52c2ac2022-03-28 17:03:35 -0700506 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700507 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700508 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
509 labels := map[string]string{"type": "tool", "name": "metalava"}
510 // TODO: metalava pool rejects these jobs
511 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
512 rule.Rewrapper(&remoteexec.REParams{
513 Labels: labels,
514 ExecStrategy: execStrategy,
515 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
516 Platform: map[string]string{remoteexec.PoolKey: pool},
517 })
Colin Cross2207f872021-03-24 12:39:08 -0700518 }
519
Colin Cross6aa5c402021-03-24 12:28:50 -0700520 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700521 Flag(config.JavacVmFlags).
522 Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
Paul Duffin808211e2023-08-09 12:36:08 +0100523 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700524 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
525 FlagWithInput("@", srcJarList)
526
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100527 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
528 // years, so it is unlikely to change any time soon.
529 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
530 combinedPaths = append(combinedPaths, classpath.Paths()...)
531 if len(combinedPaths) > 0 {
532 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700533 }
534
Mårten Kongstadbd262442023-07-12 14:01:49 +0200535 cmd.Flag("--color").
Colin Cross2207f872021-03-24 12:39:08 -0700536 Flag("--quiet").
537 Flag("--format=v2").
538 FlagWithArg("--repeat-errors-max ", "10").
Sam Gilbert09cb5db2021-10-06 11:28:28 -0400539 FlagWithArg("--hide ", "UnresolvedImport").
Ember Rose7c57af32022-04-01 10:34:44 -0400540 FlagWithArg("--hide ", "InvalidNullabilityOverride").
Sam Gilbert28e41282022-03-09 15:24:48 +0000541 // b/223382732
542 FlagWithArg("--hide ", "ChangedDefault")
Colin Cross2207f872021-03-24 12:39:08 -0700543
Paul Duffin5b7035f2023-05-31 17:51:33 +0100544 // Force metalava to ignore classes on the classpath when an API file contains missing classes.
545 // See b/285140653 for more information.
546 cmd.FlagWithArg("--api-class-resolution ", "api")
547
Paul Duffin7202ffe2023-06-01 15:28:54 +0100548 // Force metalava to sort overloaded methods by their order in the source code.
549 // See b/285312164 for more information.
Paul Duffin629b9d22023-10-10 17:50:25 +0100550 // And add concrete overrides of abstract methods, see b/299366704 for more
551 // information.
552 cmd.FlagWithArg("--format-defaults ", "overloaded-method-order=source,add-additional-overrides=yes")
Paul Duffin7202ffe2023-06-01 15:28:54 +0100553
Jihoon Kangc8313892023-09-20 00:54:47 +0000554 if ctx.DeviceConfig().HideFlaggedApis() {
555 cmd.FlagWithArg("--hide-annotation ", "android.annotation.FlaggedApi")
556 }
557
Colin Cross2207f872021-03-24 12:39:08 -0700558 return cmd
559}
560
561func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
562 deps := d.Javadoc.collectDeps(ctx)
563
Jiyong Parkf1691d22021-03-29 20:11:58 +0900564 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
Colin Cross2207f872021-03-24 12:39:08 -0700565
566 // Create rule for metalava
567
Colin Crosscb77f752021-03-24 12:04:44 -0700568 srcJarDir := android.PathForModuleOut(ctx, "metalava", "srcjars")
Colin Cross2207f872021-03-24 12:39:08 -0700569
570 rule := android.NewRuleBuilder(pctx, ctx)
571
Colin Cross8095c292021-03-30 16:40:48 -0700572 rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
573 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
574 SandboxInputs()
Colin Cross6aa5c402021-03-24 12:28:50 -0700575
Colin Cross2207f872021-03-24 12:39:08 -0700576 if BoolDefault(d.properties.High_mem, false) {
577 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
578 rule.HighMem()
579 }
580
581 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
582 var stubsDir android.OptionalPath
583 if generateStubs {
Colin Crosscb77f752021-03-24 12:04:44 -0700584 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
585 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
Colin Cross2207f872021-03-24 12:39:08 -0700586 rule.Command().Text("rm -rf").Text(stubsDir.String())
587 rule.Command().Text("mkdir -p").Text(stubsDir.String())
588 }
589
590 srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
591
Colin Crosscb77f752021-03-24 12:04:44 -0700592 homeDir := android.PathForModuleOut(ctx, "metalava", "home")
Colin Cross2207f872021-03-24 12:39:08 -0700593 cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
Anton Hansson556e8142021-06-04 16:20:25 +0100594 deps.bootClasspath, deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700595 cmd.Implicits(d.Javadoc.implicits)
596
597 d.stubsFlags(ctx, cmd, stubsDir)
598
599 d.annotationsFlags(ctx, cmd)
600 d.inclusionAnnotationsFlags(ctx, cmd)
601 d.apiLevelsAnnotationsFlags(ctx, cmd)
602
Colin Crossbc139922021-03-25 18:33:16 -0700603 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700604
Colin Cross2207f872021-03-24 12:39:08 -0700605 for _, o := range d.Javadoc.properties.Out {
606 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
607 }
608
609 // Add options for the other optional tasks: API-lint and check-released.
610 // We generate separate timestamp files for them.
611
612 doApiLint := false
613 doCheckReleased := false
614
615 // Add API lint options.
616
617 if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) {
618 doApiLint = true
619
620 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
621 if newSince.Valid() {
622 cmd.FlagWithInput("--api-lint ", newSince.Path())
623 } else {
624 cmd.Flag("--api-lint")
625 }
Colin Crosscb77f752021-03-24 12:04:44 -0700626 d.apiLintReport = android.PathForModuleOut(ctx, "metalava", "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700627 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
628
Colin Cross0d532412021-03-25 09:38:45 -0700629 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700630 if d.Name() != "android.car-system-stubs-docs" &&
631 d.Name() != "android.car-stubs-docs" {
632 cmd.Flag("--lints-as-errors")
633 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
634 }
635
636 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Colin Crosscb77f752021-03-24 12:04:44 -0700637 updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "api_lint_baseline.txt")
638 d.apiLintTimestamp = android.PathForModuleOut(ctx, "metalava", "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700639
640 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700641 //
642 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
643 // message and metalava's one?
644 msg := `$'` + // Enclose with $' ... '
645 `************************************************************\n` +
646 `Your API changes are triggering API Lint warnings or errors.\n` +
647 `To make these errors go away, fix the code according to the\n` +
648 `error and/or warning messages above.\n` +
649 `\n` +
650 `If it is not possible to do so, there are workarounds:\n` +
651 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000652 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
653 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700654
655 if baselineFile.Valid() {
656 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
657 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
658
659 msg += fmt.Sprintf(``+
660 `2. You can update the baseline by executing the following\n`+
661 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700662 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
663 ` "%s" \\\n`+
664 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700665 ` To submit the revised baseline.txt to the main Android\n`+
666 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
667 } else {
668 msg += fmt.Sprintf(``+
669 `2. You can add a baseline file of existing lint failures\n`+
670 ` to the build rule of %s.\n`, d.Name())
671 }
672 // Note the message ends with a ' (single quote), to close the $' ... ' .
673 msg += `************************************************************\n'`
674
675 cmd.FlagWithArg("--error-message:api-lint ", msg)
676 }
677
678 // Add "check released" options. (Detect incompatible API changes from the last public release)
679
680 if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
681 doCheckReleased = true
682
683 if len(d.Javadoc.properties.Out) > 0 {
684 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
685 }
686
687 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
688 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
689 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Colin Crosscb77f752021-03-24 12:04:44 -0700690 updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700691
Colin Crosscb77f752021-03-24 12:04:44 -0700692 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700693
694 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
695 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
696
697 if baselineFile.Valid() {
698 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
699 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
700 }
701
702 // Note this string includes quote ($' ... '), which decodes the "\n"s.
703 msg := `$'\n******************************\n` +
704 `You have tried to change the API from what has been previously released in\n` +
705 `an SDK. Please fix the errors listed above.\n` +
706 `******************************\n'`
707
708 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
709 }
710
Paul Duffin10a23c22023-08-11 22:47:31 +0100711 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
712 // Pass the current API file into metalava so it can use it as the basis for determining how to
713 // generate the output signature files (both api and removed).
714 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
715 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
716 }
717
Colin Cross2207f872021-03-24 12:39:08 -0700718 if generateStubs {
719 rule.Command().
720 BuiltTool("soong_zip").
721 Flag("-write_if_changed").
722 Flag("-jar").
723 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
724 FlagWithArg("-C ", stubsDir.String()).
725 FlagWithArg("-D ", stubsDir.String())
726 }
727
728 if Bool(d.properties.Write_sdk_values) {
Colin Crosscb77f752021-03-24 12:04:44 -0700729 d.metadataZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-metadata.zip")
Colin Cross2207f872021-03-24 12:39:08 -0700730 rule.Command().
731 BuiltTool("soong_zip").
732 Flag("-write_if_changed").
733 Flag("-d").
734 FlagWithOutput("-o ", d.metadataZip).
735 FlagWithArg("-C ", d.metadataDir.String()).
736 FlagWithArg("-D ", d.metadataDir.String())
737 }
738
739 // TODO: We don't really need two separate API files, but this is a reminiscence of how
740 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
741 if doApiLint {
742 rule.Command().Text("touch").Output(d.apiLintTimestamp)
743 }
744 if doCheckReleased {
745 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
746 }
747
Colin Cross6aa5c402021-03-24 12:28:50 -0700748 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -0700749 if !metalavaUseRbe(ctx) {
750 rule.Restat()
751 }
Colin Cross2207f872021-03-24 12:39:08 -0700752
753 zipSyncCleanupCmd(rule, srcJarDir)
754
Paul Duffinc166b682022-05-27 12:23:08 +0000755 rule.Build("metalava", "metalava merged")
756
Paul Duffine7a86642022-08-16 15:43:20 +0000757 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
758
759 if len(d.Javadoc.properties.Out) > 0 {
760 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
761 }
762
763 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
764 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
765 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
766
767 if baselineFile.Valid() {
768 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
769 }
770
771 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_current_api.timestamp")
772
773 rule := android.NewRuleBuilder(pctx, ctx)
774
775 // Diff command line.
776 // -F matches the closest "opening" line, such as "package android {"
777 // and " public class Intent {".
778 diff := `diff -u -F '{ *$'`
779
780 rule.Command().Text("( true")
781 rule.Command().
782 Text(diff).
783 Input(apiFile).Input(d.apiFile)
784
785 rule.Command().
786 Text(diff).
787 Input(removedApiFile).Input(d.removedApiFile)
788
789 msg := fmt.Sprintf(`\n******************************\n`+
790 `You have tried to change the API from what has been previously approved.\n\n`+
791 `To make these errors go away, you have two choices:\n`+
792 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
793 ` to the new methods, etc. shown in the above diff.\n\n`+
794 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
795 ` m %s-update-current-api\n\n`+
796 ` To submit the revised current.txt to the main Android repository,\n`+
797 ` you will need approval.\n`+
798 `******************************\n`, ctx.ModuleName())
799
800 rule.Command().
801 Text("touch").Output(d.checkCurrentApiTimestamp).
802 Text(") || (").
803 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
804 Text("; exit 38").
805 Text(")")
806
807 rule.Build("metalavaCurrentApiCheck", "check current API")
808
809 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "update_current_api.timestamp")
810
811 // update API rule
812 rule = android.NewRuleBuilder(pctx, ctx)
813
814 rule.Command().Text("( true")
815
816 rule.Command().
817 Text("cp").Flag("-f").
818 Input(d.apiFile).Flag(apiFile.String())
819
820 rule.Command().
821 Text("cp").Flag("-f").
822 Input(d.removedApiFile).Flag(removedApiFile.String())
823
824 msg = "failed to update public API"
825
826 rule.Command().
827 Text("touch").Output(d.updateCurrentApiTimestamp).
828 Text(") || (").
829 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
830 Text("; exit 38").
831 Text(")")
832
833 rule.Build("metalavaCurrentApiUpdate", "update current API")
834 }
835
Colin Cross2207f872021-03-24 12:39:08 -0700836 if String(d.properties.Check_nullability_warnings) != "" {
837 if d.nullabilityWarningsFile == nil {
838 ctx.PropertyErrorf("check_nullability_warnings",
839 "Cannot specify check_nullability_warnings unless validating nullability")
840 }
841
842 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
843
Colin Crosscb77f752021-03-24 12:04:44 -0700844 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "metalava", "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700845
846 msg := fmt.Sprintf(`\n******************************\n`+
847 `The warnings encountered during nullability annotation validation did\n`+
848 `not match the checked in file of expected warnings. The diffs are shown\n`+
849 `above. You have two options:\n`+
850 ` 1. Resolve the differences by editing the nullability annotations.\n`+
851 ` 2. Update the file of expected warnings by running:\n`+
852 ` cp %s %s\n`+
853 ` and submitting the updated file as part of your change.`,
854 d.nullabilityWarningsFile, checkNullabilityWarnings)
855
856 rule := android.NewRuleBuilder(pctx, ctx)
857
858 rule.Command().
859 Text("(").
860 Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
861 Text("&&").
862 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
863 Text(") || (").
864 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
865 Text("; exit 38").
866 Text(")")
867
868 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
869 }
870}
871
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000872func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
873 api_file := d.properties.Check_api.Current.Api_file
874 api_surface := d.properties.Api_surface
875
876 props := struct {
877 Name *string
878 Api_surface *string
879 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +0000880 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000881 }{}
882
883 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
884 props.Api_surface = api_surface
885 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +0000886 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000887
888 ctx.CreateModule(ApiContributionFactory, &props)
889}
890
Spandan Das0b555e32022-11-28 18:48:51 +0000891// TODO (b/262014796): Export the API contributions of CorePlatformApi
892// A map to populate the api surface of a droidstub from a substring appearing in its name
893// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
894// use a strict naming convention
895var (
896 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
897 //public is commented out since the core libraries use public in their java_sdk_library names
898 "intracore": android.SdkIntraCore,
899 "intra.core": android.SdkIntraCore,
900 "system_server": android.SdkSystemServer,
901 "system-server": android.SdkSystemServer,
902 "system": android.SdkSystem,
903 "module_lib": android.SdkModule,
904 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +0000905 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +0000906 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +0000907 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +0000908 }
909)
910
911// A helper function that returns the api surface of the corresponding java_api_contribution Bazel target
912// The api_surface is populated using the naming convention of the droidstubs module.
913func bazelApiSurfaceName(name string) string {
914 // Sort the keys so that longer strings appear first
915 // Otherwise substrings like system will match both system and system_server
916 sortedKeys := make([]string, 0)
917 for key := range droidstubsModuleNamingToSdkKind {
918 sortedKeys = append(sortedKeys, key)
919 }
920 sort.Slice(sortedKeys, func(i, j int) bool {
921 return len(sortedKeys[i]) > len(sortedKeys[j])
922 })
923 for _, sortedKey := range sortedKeys {
924 if strings.Contains(name, sortedKey) {
925 sdkKind := droidstubsModuleNamingToSdkKind[sortedKey]
926 return sdkKind.String() + "api"
927 }
928 }
929 // Default is publicapi
930 return android.SdkPublic.String() + "api"
931}
932
Colin Cross2207f872021-03-24 12:39:08 -0700933func StubsDefaultsFactory() android.Module {
934 module := &DocDefaults{}
935
936 module.AddProperties(
937 &JavadocProperties{},
938 &DroidstubsProperties{},
939 )
940
941 android.InitDefaultsModule(module)
942
943 return module
944}
945
946var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
947
948type PrebuiltStubsSourcesProperties struct {
949 Srcs []string `android:"path"`
950}
951
952type PrebuiltStubsSources struct {
953 android.ModuleBase
954 android.DefaultableModuleBase
955 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -0700956
957 properties PrebuiltStubsSourcesProperties
958
kgui67007242022-01-25 13:50:25 +0800959 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -0700960}
961
962func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
963 switch tag {
964 case "":
965 return android.Paths{p.stubsSrcJar}, nil
966 default:
967 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
968 }
969}
970
971func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
972 return d.stubsSrcJar
973}
974
975func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -0700976 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +0000977 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 -0700978 return
979 }
980
Anton Hansson86758ac2021-11-03 14:44:12 +0000981 src := p.properties.Srcs[0]
982 if filepath.Ext(src) == ".srcjar" {
983 // This is a srcjar. We can use it directly.
984 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
985 } else {
986 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -0700987
Anton Hansson86758ac2021-11-03 14:44:12 +0000988 // This is a directory. Glob the contents just in case the directory does not exist.
989 srcGlob := src + "/**/*"
990 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -0700991
Anton Hansson86758ac2021-11-03 14:44:12 +0000992 // Although PathForModuleSrc can return nil if either the path doesn't exist or
993 // the path components are invalid it won't in this case because no components
994 // are specified and the module directory must exist in order to get this far.
995 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -0700996
Anton Hansson86758ac2021-11-03 14:44:12 +0000997 rule := android.NewRuleBuilder(pctx, ctx)
998 rule.Command().
999 BuiltTool("soong_zip").
1000 Flag("-write_if_changed").
1001 Flag("-jar").
1002 FlagWithOutput("-o ", outPath).
1003 FlagWithArg("-C ", srcDir.String()).
1004 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1005 rule.Restat()
1006 rule.Build("zip src", "Create srcjar from prebuilt source")
1007 p.stubsSrcJar = outPath
1008 }
Colin Cross2207f872021-03-24 12:39:08 -07001009}
1010
1011func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1012 return &p.prebuilt
1013}
1014
1015func (p *PrebuiltStubsSources) Name() string {
1016 return p.prebuilt.Name(p.ModuleBase.Name())
1017}
1018
1019// prebuilt_stubs_sources imports a set of java source files as if they were
1020// generated by droidstubs.
1021//
1022// By default, a prebuilt_stubs_sources has a single variant that expects a
1023// set of `.java` files generated by droidstubs.
1024//
1025// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1026// for host modules.
1027//
1028// Intended only for use by sdk snapshots.
1029func PrebuiltStubsSourcesFactory() android.Module {
1030 module := &PrebuiltStubsSources{}
1031
1032 module.AddProperties(&module.properties)
1033
1034 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001035 InitDroiddocModule(module, android.HostAndDeviceSupported)
1036 return module
1037}