blob: 51503f22ac0514e0f1b34c90b01ae8c354121f6b [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
Jihoon Kangee113282024-01-23 00:16:41 +000068type stubsArtifacts struct {
69 nullabilityWarningsFile android.WritablePath
70 annotationsZip android.WritablePath
71 apiVersionsXml android.WritablePath
72 metadataZip android.WritablePath
73 metadataDir android.WritablePath
74}
75
Colin Cross2207f872021-03-24 12:39:08 -070076// Droidstubs
Colin Cross2207f872021-03-24 12:39:08 -070077type Droidstubs struct {
78 Javadoc
Spandan Das2cc80ba2023-10-27 17:21:52 +000079 embeddableInModuleAndImport
Colin Cross2207f872021-03-24 12:39:08 -070080
Jihoon Kangee113282024-01-23 00:16:41 +000081 properties DroidstubsProperties
82 apiFile android.Path
83 removedApiFile android.Path
Colin Cross2207f872021-03-24 12:39:08 -070084
85 checkCurrentApiTimestamp android.WritablePath
86 updateCurrentApiTimestamp android.WritablePath
87 checkLastReleasedApiTimestamp android.WritablePath
88 apiLintTimestamp android.WritablePath
89 apiLintReport android.WritablePath
90
91 checkNullabilityWarningsTimestamp android.WritablePath
92
Jihoon Kangee113282024-01-23 00:16:41 +000093 everythingArtifacts stubsArtifacts
94 exportableArtifacts stubsArtifacts
Jihoon Kang3c89f042023-12-19 02:40:22 +000095
LaMont Jonesafe7baf2024-01-09 22:47:39 +000096 // Single aconfig "cache file" merged from this module and all dependencies.
97 mergedAconfigFiles map[string]android.Paths
98
Jihoon Kangee113282024-01-23 00:16:41 +000099 exportableApiFile android.WritablePath
100 exportableRemovedApiFile android.WritablePath
Colin Cross2207f872021-03-24 12:39:08 -0700101}
102
103type DroidstubsProperties struct {
104 // The generated public API filename by Metalava, defaults to <module>_api.txt
105 Api_filename *string
106
107 // the generated removed API filename by Metalava, defaults to <module>_removed.txt
108 Removed_api_filename *string
109
Colin Cross2207f872021-03-24 12:39:08 -0700110 Check_api struct {
111 Last_released ApiToCheck
112
113 Current ApiToCheck
114
115 Api_lint struct {
116 Enabled *bool
117
118 // If set, performs api_lint on any new APIs not found in the given signature file
119 New_since *string `android:"path"`
120
121 // If not blank, path to the baseline txt file for approved API lint violations.
122 Baseline_file *string `android:"path"`
123 }
124 }
125
126 // user can specify the version of previous released API file in order to do compatibility check.
127 Previous_api *string `android:"path"`
128
129 // is set to true, Metalava will allow framework SDK to contain annotations.
130 Annotations_enabled *bool
131
132 // a list of top-level directories containing files to merge qualifier annotations (i.e. those intended to be included in the stubs written) from.
133 Merge_annotations_dirs []string
134
135 // a list of top-level directories containing Java stub files to merge show/hide annotations from.
136 Merge_inclusion_annotations_dirs []string
137
138 // a file containing a list of classes to do nullability validation for.
139 Validate_nullability_from_list *string
140
141 // a file containing expected warnings produced by validation of nullability annotations.
142 Check_nullability_warnings *string
143
144 // if set to true, allow Metalava to generate doc_stubs source files. Defaults to false.
145 Create_doc_stubs *bool
146
147 // if set to true, cause Metalava to output Javadoc comments in the stubs source files. Defaults to false.
148 // Has no effect if create_doc_stubs: true.
149 Output_javadoc_comments *bool
150
151 // if set to false then do not write out stubs. Defaults to true.
152 //
153 // TODO(b/146727827): Remove capability when we do not need to generate stubs and API separately.
154 Generate_stubs *bool
155
156 // 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 -0400157 // which can be used for scheduling purposes
Colin Cross2207f872021-03-24 12:39:08 -0700158 High_mem *bool
159
satayev783195c2021-06-23 21:49:57 +0100160 // if set to true, Metalava will allow framework SDK to contain API levels annotations.
Colin Cross2207f872021-03-24 12:39:08 -0700161 Api_levels_annotations_enabled *bool
162
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000163 // Apply the api levels database created by this module rather than generating one in this droidstubs.
164 Api_levels_module *string
165
Colin Cross2207f872021-03-24 12:39:08 -0700166 // the dirs which Metalava extracts API levels annotations from.
167 Api_levels_annotations_dirs []string
168
Cole Faust051fa912022-10-05 12:45:42 -0700169 // 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 +0100170 Api_levels_sdk_type *string
171
Colin Cross2207f872021-03-24 12:39:08 -0700172 // the filename which Metalava extracts API levels annotations from. Defaults to android.jar.
173 Api_levels_jar_filename *string
174
175 // if set to true, collect the values used by the Dev tools and
176 // write them in files packaged with the SDK. Defaults to false.
177 Write_sdk_values *bool
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200178
179 // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and
180 // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info
181 Extensions_info_file *string `android:"path"`
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000182
183 // API surface of this module. If set, the module contributes to an API surface.
184 // For the full list of available API surfaces, refer to soong/android/sdk_version.go
185 Api_surface *string
Jihoon Kang6592e872023-12-19 01:13:16 +0000186
187 // a list of aconfig_declarations module names that the stubs generated in this module
188 // depend on.
189 Aconfig_declarations []string
Colin Cross2207f872021-03-24 12:39:08 -0700190}
191
Anton Hansson52609322021-05-05 10:36:05 +0100192// Used by xsd_config
193type ApiFilePath interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000194 ApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100195}
196
197type ApiStubsSrcProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000198 StubsSrcJar(StubsType) (android.Path, error)
Jihoon Kangf55a5f72024-01-08 08:56:20 +0000199}
200
Anton Hansson52609322021-05-05 10:36:05 +0100201// Provider of information about API stubs, used by java_sdk_library.
202type ApiStubsProvider interface {
Jihoon Kangee113282024-01-23 00:16:41 +0000203 AnnotationsZip(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100204 ApiFilePath
Jihoon Kangee113282024-01-23 00:16:41 +0000205 RemovedApiFilePath(StubsType) (android.Path, error)
Anton Hansson52609322021-05-05 10:36:05 +0100206
207 ApiStubsSrcProvider
208}
209
Jihoon Kang063ec002023-06-28 01:16:23 +0000210type currentApiTimestampProvider interface {
211 CurrentApiTimestamp() android.Path
212}
213
Jihoon Kang3c89f042023-12-19 02:40:22 +0000214type annotationFlagsParams struct {
215 migratingNullability bool
216 validatingNullability bool
217 nullabilityWarningsFile android.WritablePath
218 annotationsZip android.WritablePath
219}
220type stubsCommandParams struct {
221 srcJarDir android.ModuleOutPath
222 stubsDir android.OptionalPath
223 stubsSrcJar android.WritablePath
224 metadataZip android.WritablePath
225 metadataDir android.WritablePath
226 apiVersionsXml android.WritablePath
227 nullabilityWarningsFile android.WritablePath
228 annotationsZip android.WritablePath
229 stubConfig stubsCommandConfigParams
230}
231type stubsCommandConfigParams struct {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000232 stubsType StubsType
233 javaVersion javaVersion
234 deps deps
235 checkApi bool
236 generateStubs bool
237 doApiLint bool
238 doCheckReleased bool
239 writeSdkValues bool
240 migratingNullability bool
241 validatingNullability bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000242}
243
Colin Cross2207f872021-03-24 12:39:08 -0700244// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
245// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
246// a droiddoc module to generate documentation.
247func DroidstubsFactory() android.Module {
248 module := &Droidstubs{}
249
250 module.AddProperties(&module.properties,
251 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000252 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700253
254 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000255
256 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
257 module.createApiContribution(ctx)
258 })
Colin Cross2207f872021-03-24 12:39:08 -0700259 return module
260}
261
262// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
263// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
264// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
265// module when symbols needed by the source files are provided by java_library_host modules.
266func DroidstubsHostFactory() android.Module {
267 module := &Droidstubs{}
268
269 module.AddProperties(&module.properties,
270 &module.Javadoc.properties)
271
272 InitDroiddocModule(module, android.HostSupported)
273 return module
274}
275
Jihoon Kang78f89142023-12-27 01:40:29 +0000276func getStubsTypeAndTag(tag string) (StubsType, string, error) {
277 if len(tag) == 0 {
278 return Everything, "", nil
279 }
280 if tag[0] != '.' {
281 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
282 }
283
284 stubsType := Everything
285 // Check if the tag has a stubs type prefix (e.g. ".exportable")
286 for st := Everything; st <= Exportable; st++ {
287 if strings.HasPrefix(tag, "."+st.String()) {
288 stubsType = st
289 }
290 }
291
292 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
293}
294
295// Droidstubs' tag supports specifying with the stubs type.
296// While supporting the pre-existing tags, it also supports tags with
297// the stubs type prefix. Some examples are shown below:
298// {.annotations.zip} - pre-existing behavior. Returns the path to the
299// annotation zip.
300// {.exportable} - Returns the path to the exportable stubs src jar.
301// {.exportable.annotations.zip} - Returns the path to the exportable
302// annotations zip file.
303// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
304// xml file. For unsupported combinations, the default everything output file
305// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700306func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000307 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
308 if err != nil {
309 return nil, err
310 }
311 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700312 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000313 stubsSrcJar, err := d.StubsSrcJar(stubsType)
314 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700315 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000316 docZip, err := d.DocZip(stubsType)
317 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700318 case ".api.txt", android.DefaultDistTag:
319 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000320 apiFilePath, err := d.ApiFilePath(stubsType)
321 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700322 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000323 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
324 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700325 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000326 annotationsZip, err := d.AnnotationsZip(stubsType)
327 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700328 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000329 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
330 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700331 default:
332 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
333 }
334}
335
Jihoon Kang246690a2024-02-01 21:55:01 +0000336func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000337 switch stubsType {
338 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000339 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000340 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000341 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000342 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000343 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000344 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000345 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000346}
347
Jihoon Kang246690a2024-02-01 21:55:01 +0000348func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000349 switch stubsType {
350 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000351 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000352 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000353 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000354 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000355 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000356 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000357 if ret == nil && err == nil {
358 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
359 }
360 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000361}
362
Jihoon Kang246690a2024-02-01 21:55:01 +0000363func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000364 switch stubsType {
365 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000366 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000367 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000368 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000369 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000371 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 if ret == nil && err == nil {
373 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
374 }
375 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000376}
377
Jihoon Kang246690a2024-02-01 21:55:01 +0000378func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000379 switch stubsType {
380 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000381 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000382 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000383 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000384 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 if ret == nil && err == nil {
386 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
387 }
388 return ret, err
389}
390
391func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
392 switch stubsType {
393 case Everything:
394 ret, err = d.removedApiFile, nil
395 case Exportable:
396 ret, err = d.exportableRemovedApiFile, nil
397 default:
398 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
399 }
400 if ret == nil && err == nil {
401 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
402 }
403 return ret, err
404}
405
406func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
407 switch stubsType {
408 case Everything:
409 ret, err = d.stubsSrcJar, nil
410 case Exportable:
411 ret, err = d.exportableStubsSrcJar, nil
412 default:
413 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
414 }
415 if ret == nil && err == nil {
416 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
417 }
418 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000419}
420
Jihoon Kang063ec002023-06-28 01:16:23 +0000421func (d *Droidstubs) CurrentApiTimestamp() android.Path {
422 return d.checkCurrentApiTimestamp
423}
424
Colin Cross2207f872021-03-24 12:39:08 -0700425var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
426var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
427var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000428var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000429var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700430
431func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
432 d.Javadoc.addDeps(ctx)
433
434 if len(d.properties.Merge_annotations_dirs) != 0 {
435 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
436 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
437 }
438 }
439
440 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
441 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
442 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
443 }
444 }
445
446 if len(d.properties.Api_levels_annotations_dirs) != 0 {
447 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
448 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
449 }
450 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000451
Jihoon Kang6592e872023-12-19 01:13:16 +0000452 if len(d.properties.Aconfig_declarations) != 0 {
453 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
454 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
455 }
456 }
457
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000458 if d.properties.Api_levels_module != nil {
459 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
460 }
Colin Cross2207f872021-03-24 12:39:08 -0700461}
462
Jihoon Kang3c89f042023-12-19 02:40:22 +0000463func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
464 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
465}
466
467func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
468 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700469 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000470 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000471 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000472
473 if stubsType == Everything {
474 d.apiFile = uncheckedApiFile
475 } else if stubsType == Exportable {
476 d.exportableApiFile = uncheckedApiFile
477 }
Colin Cross2207f872021-03-24 12:39:08 -0700478 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
479 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000480 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700481 }
482
Jihoon Kang3c89f042023-12-19 02:40:22 +0000483 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700484 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000485 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000486 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487
488 if stubsType == Everything {
489 d.removedApiFile = uncheckedRemovedFile
490 } else if stubsType == Exportable {
491 d.exportableRemovedApiFile = uncheckedRemovedFile
492 }
Colin Cross2207f872021-03-24 12:39:08 -0700493 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
494 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000495 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700496 }
497
Colin Cross2207f872021-03-24 12:39:08 -0700498 if stubsDir.Valid() {
499 if Bool(d.properties.Create_doc_stubs) {
500 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
501 } else {
502 cmd.FlagWithArg("--stubs ", stubsDir.String())
503 if !Bool(d.properties.Output_javadoc_comments) {
504 cmd.Flag("--exclude-documentation-from-stubs")
505 }
506 }
507 }
508}
509
Jihoon Kang3c89f042023-12-19 02:40:22 +0000510func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kanga11d6792024-03-05 16:12:20 +0000511 if Bool(d.properties.Annotations_enabled) {
512 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100513
Jihoon Kanga11d6792024-03-05 16:12:20 +0000514 if params.migratingNullability {
515 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
516 cmd.FlagWithInput("--migrate-nullness ", previousApi)
517 }
518
519 if s := String(d.properties.Validate_nullability_from_list); s != "" {
520 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
521 }
522
523 if params.validatingNullability {
524 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
525 }
526
527 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
528
529 if len(d.properties.Merge_annotations_dirs) != 0 {
530 d.mergeAnnoDirFlags(ctx, cmd)
531 }
532
533 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700534 }
535}
536
537func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
538 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
539 if t, ok := m.(*ExportedDroiddocDir); ok {
540 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
541 } else {
542 ctx.PropertyErrorf("merge_annotations_dirs",
543 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
544 }
545 })
546}
547
548func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
549 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
550 if t, ok := m.(*ExportedDroiddocDir); ok {
551 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
552 } else {
553 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
554 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
555 }
556 })
557}
558
Jihoon Kanga11d6792024-03-05 16:12:20 +0000559func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000560 var apiVersions android.Path
Jihoon Kanga11d6792024-03-05 16:12:20 +0000561 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000562 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000563 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000564 } else {
565 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
566 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000567 if stubsType == Everything {
568 apiVersions = s.everythingArtifacts.apiVersionsXml
569 } else if stubsType == Exportable {
570 apiVersions = s.exportableArtifacts.apiVersionsXml
571 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000572 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000573 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000574 } else {
575 ctx.PropertyErrorf("api_levels_module",
576 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
577 }
578 })
Colin Cross2207f872021-03-24 12:39:08 -0700579 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000580 if apiVersions != nil {
581 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
582 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
583 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
584 }
585}
Colin Cross2207f872021-03-24 12:39:08 -0700586
Jihoon Kang3c89f042023-12-19 02:40:22 +0000587func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700588 if len(d.properties.Api_levels_annotations_dirs) == 0 {
589 ctx.PropertyErrorf("api_levels_annotations_dirs",
590 "has to be non-empty if api levels annotations was enabled!")
591 }
592
Jihoon Kang3c89f042023-12-19 02:40:22 +0000593 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700594
595 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
596
satayev783195c2021-06-23 21:49:57 +0100597 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200598 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700599 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
600 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200601 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
602
603 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
604 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700605 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200606 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
607 if extensions_dir == "" {
608 extensions_dir = t.dir.String() + "/extensions"
609 }
610 cmd.Implicit(dep)
611 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700612 if dep.Base() == filename {
613 cmd.Implicit(dep)
614 }
615 if filename != "android.jar" && dep.Base() == "android.jar" {
616 // Metalava implicitly searches these patterns:
617 // prebuilts/tools/common/api-versions/android-%/android.jar
618 // prebuilts/sdk/%/public/android.jar
619 // Add android.jar files from the api_levels_annotations_dirs directories to try
620 // to satisfy these patterns. If Metalava can't find a match for an API level
621 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700622 cmd.Implicit(dep)
623 }
624 }
satayev783195c2021-06-23 21:49:57 +0100625
626 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700627 } else {
628 ctx.PropertyErrorf("api_levels_annotations_dirs",
629 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
630 }
631 })
satayev783195c2021-06-23 21:49:57 +0100632
633 // Add all relevant --android-jar-pattern patterns for Metalava.
634 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
635 // an actual file present on disk (in the order the patterns were passed). For system APIs for
636 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000637 // for older releases. Similarly, module-lib falls back to system API.
638 var sdkDirs []string
639 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700640 case "system-server":
641 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000642 case "module-lib":
643 sdkDirs = []string{"module-lib", "system", "public"}
644 case "system":
645 sdkDirs = []string{"system", "public"}
646 case "public":
647 sdkDirs = []string{"public"}
648 default:
649 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
650 return
satayev783195c2021-06-23 21:49:57 +0100651 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000652
653 for _, sdkDir := range sdkDirs {
654 for _, dir := range dirs {
655 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
656 }
satayev783195c2021-06-23 21:49:57 +0100657 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200658
659 if d.properties.Extensions_info_file != nil {
660 if extensions_dir == "" {
661 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
662 }
663 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
664 cmd.Implicit(info_file)
665 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
666 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
667 }
Colin Cross2207f872021-03-24 12:39:08 -0700668}
669
Colin Crosse52c2ac2022-03-28 17:03:35 -0700670func metalavaUseRbe(ctx android.ModuleContext) bool {
671 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
672}
673
Colin Cross2207f872021-03-24 12:39:08 -0700674func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100675 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700676 rule.Command().Text("rm -rf").Flag(homeDir.String())
677 rule.Command().Text("mkdir -p").Flag(homeDir.String())
678
Anton Hansson556e8142021-06-04 16:20:25 +0100679 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700680 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
681
Colin Crosse52c2ac2022-03-28 17:03:35 -0700682 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700683 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700684 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000685 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
686 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700687 labels := map[string]string{"type": "tool", "name": "metalava"}
688 // TODO: metalava pool rejects these jobs
689 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
690 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000691 Labels: labels,
692 ExecStrategy: execStrategy,
693 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
694 Platform: map[string]string{remoteexec.PoolKey: pool},
695 Compare: compare,
696 NumLocalRuns: 1,
697 NumRemoteRuns: 1,
698 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700699 })
Colin Cross2207f872021-03-24 12:39:08 -0700700 }
701
Colin Cross6aa5c402021-03-24 12:28:50 -0700702 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700703 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400704 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100705 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700706 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
707 FlagWithInput("@", srcJarList)
708
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100709 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
710 // years, so it is unlikely to change any time soon.
711 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
712 combinedPaths = append(combinedPaths, classpath.Paths()...)
713 if len(combinedPaths) > 0 {
714 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700715 }
716
Liz Kammere09e20e2023-10-16 15:07:54 -0400717 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000718
Colin Cross2207f872021-03-24 12:39:08 -0700719 return cmd
720}
721
Jihoon Kang3c89f042023-12-19 02:40:22 +0000722// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
723// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
724// property is defined, apply transformations and only revert the flagged apis that are not
725// enabled via release configurations and are not specified in aconfig_declarations
726func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
727
728 if len(aconfigFlagsPaths) == 0 {
729 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
730 return
731 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000732
733 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
734 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
735
736 var filterArgs string
737 switch stubsType {
738 // No flagged apis specific flags need to be passed to metalava when generating
739 // everything stubs
740 case Everything:
741 return
742
743 case Runtime:
744 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
745
746 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000747 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
748 // the flagged apis that have read_write permissions are exposed on top of the enabled
749 // and read_only apis. This is to support local override of flag values at runtime.
750 if ctx.Config().ReleaseExportRuntimeApis() {
751 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
752 } else {
753 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
754 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000755 }
756
757 ctx.Build(pctx, android.BuildParams{
758 Rule: gatherReleasedFlaggedApisRule,
759 Inputs: aconfigFlagsPaths,
760 Output: releasedFlaggedApisFile,
761 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
762 Args: map[string]string{
763 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
764 "filter_args": filterArgs,
765 },
766 })
767
768 ctx.Build(pctx, android.BuildParams{
769 Rule: generateMetalavaRevertAnnotationsRule,
770 Input: releasedFlaggedApisFile,
771 Output: revertAnnotationsFile,
772 Description: fmt.Sprintf("%s revert annotations", stubsType),
773 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000774
775 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000776}
777
Jihoon Kang3c89f042023-12-19 02:40:22 +0000778func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
779 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700780 if BoolDefault(d.properties.High_mem, false) {
781 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
782 rule.HighMem()
783 }
784
Jihoon Kang3c89f042023-12-19 02:40:22 +0000785 if params.stubConfig.generateStubs {
786 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
787 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700788 }
789
Jihoon Kang3c89f042023-12-19 02:40:22 +0000790 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700791
Jihoon Kang3c89f042023-12-19 02:40:22 +0000792 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
793 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
794 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700795 cmd.Implicits(d.Javadoc.implicits)
796
Jihoon Kang3c89f042023-12-19 02:40:22 +0000797 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700798
Jihoon Kang3c89f042023-12-19 02:40:22 +0000799 if params.stubConfig.writeSdkValues {
800 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
801 }
802
803 annotationParams := annotationFlagsParams{
804 migratingNullability: params.stubConfig.migratingNullability,
805 validatingNullability: params.stubConfig.validatingNullability,
806 nullabilityWarningsFile: params.nullabilityWarningsFile,
807 annotationsZip: params.annotationsZip,
808 }
809
Jihoon Kanga11d6792024-03-05 16:12:20 +0000810 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700811 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kanga11d6792024-03-05 16:12:20 +0000812 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700813
Colin Crossbc139922021-03-25 18:33:16 -0700814 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700815
Colin Cross2207f872021-03-24 12:39:08 -0700816 for _, o := range d.Javadoc.properties.Out {
817 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
818 }
819
Jihoon Kang3c89f042023-12-19 02:40:22 +0000820 return cmd
821}
Colin Cross2207f872021-03-24 12:39:08 -0700822
Jihoon Kang3c89f042023-12-19 02:40:22 +0000823// Sandbox rule for generating the everything stubs and other artifacts
824func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
825 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
826 rule := android.NewRuleBuilder(pctx, ctx)
827 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
828 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
829 SandboxInputs()
830
831 var stubsDir android.OptionalPath
832 if params.generateStubs {
833 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
834 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
835 }
836
837 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000838 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
839 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000840 }
841
Jihoon Kanga11d6792024-03-05 16:12:20 +0000842 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000843 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000844 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000845 }
Jihoon Kangee113282024-01-23 00:16:41 +0000846 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000847 }
Jihoon Kanga11d6792024-03-05 16:12:20 +0000848 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000849 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000850 }
851
852 commonCmdParams := stubsCommandParams{
853 srcJarDir: srcJarDir,
854 stubsDir: stubsDir,
855 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000856 metadataDir: d.everythingArtifacts.metadataDir,
857 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
858 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
859 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000860 stubConfig: params,
861 }
862
863 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
864
865 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
866
867 if params.generateStubs {
868 rule.Command().
869 BuiltTool("soong_zip").
870 Flag("-write_if_changed").
871 Flag("-jar").
872 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
873 FlagWithArg("-C ", stubsDir.String()).
874 FlagWithArg("-D ", stubsDir.String())
875 }
876
877 if params.writeSdkValues {
878 rule.Command().
879 BuiltTool("soong_zip").
880 Flag("-write_if_changed").
881 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000882 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
883 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
884 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000885 }
886
887 // TODO: We don't really need two separate API files, but this is a reminiscence of how
888 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
889 if params.doApiLint {
890 rule.Command().Text("touch").Output(d.apiLintTimestamp)
891 }
892 if params.doCheckReleased {
893 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
894 }
895
896 // TODO(b/183630617): rewrapper doesn't support restat rules
897 if !metalavaUseRbe(ctx) {
898 rule.Restat()
899 }
900
901 zipSyncCleanupCmd(rule, srcJarDir)
902
903 rule.Build("metalava", "metalava merged")
904}
905
906// Sandbox rule for generating the everything artifacts that are not run by
907// default but only run based on the module configurations
908func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700909
910 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000911 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700912 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
913 if newSince.Valid() {
914 cmd.FlagWithInput("--api-lint ", newSince.Path())
915 } else {
916 cmd.Flag("--api-lint")
917 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000918 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700919 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
920
Colin Cross0d532412021-03-25 09:38:45 -0700921 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700922 if d.Name() != "android.car-system-stubs-docs" &&
923 d.Name() != "android.car-stubs-docs" {
924 cmd.Flag("--lints-as-errors")
925 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
926 }
927
928 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000929 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
930 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700931
932 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700933 //
934 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
935 // message and metalava's one?
936 msg := `$'` + // Enclose with $' ... '
937 `************************************************************\n` +
938 `Your API changes are triggering API Lint warnings or errors.\n` +
939 `To make these errors go away, fix the code according to the\n` +
940 `error and/or warning messages above.\n` +
941 `\n` +
942 `If it is not possible to do so, there are workarounds:\n` +
943 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000944 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
945 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700946
947 if baselineFile.Valid() {
948 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
949 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
950
951 msg += fmt.Sprintf(``+
952 `2. You can update the baseline by executing the following\n`+
953 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700954 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
955 ` "%s" \\\n`+
956 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700957 ` To submit the revised baseline.txt to the main Android\n`+
958 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
959 } else {
960 msg += fmt.Sprintf(``+
961 `2. You can add a baseline file of existing lint failures\n`+
962 ` to the build rule of %s.\n`, d.Name())
963 }
964 // Note the message ends with a ' (single quote), to close the $' ... ' .
965 msg += `************************************************************\n'`
966
967 cmd.FlagWithArg("--error-message:api-lint ", msg)
968 }
969
970 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000971 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700972 if len(d.Javadoc.properties.Out) > 0 {
973 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
974 }
975
976 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
977 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
978 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000979 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700980
Jihoon Kang3c89f042023-12-19 02:40:22 +0000981 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700982
983 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
984 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
985
986 if baselineFile.Valid() {
987 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
988 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
989 }
990
991 // Note this string includes quote ($' ... '), which decodes the "\n"s.
992 msg := `$'\n******************************\n` +
993 `You have tried to change the API from what has been previously released in\n` +
994 `an SDK. Please fix the errors listed above.\n` +
995 `******************************\n'`
996
997 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
998 }
999
Paul Duffin10a23c22023-08-11 22:47:31 +01001000 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1001 // Pass the current API file into metalava so it can use it as the basis for determining how to
1002 // generate the output signature files (both api and removed).
1003 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1004 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1005 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001006}
Paul Duffin10a23c22023-08-11 22:47:31 +01001007
Jihoon Kang3c89f042023-12-19 02:40:22 +00001008// Sandbox rule for generating exportable stubs and other artifacts
1009func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1010 optionalCmdParams := stubsCommandParams{
1011 stubConfig: params,
1012 }
1013
Jihoon Kang246690a2024-02-01 21:55:01 +00001014 if params.generateStubs {
1015 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1016 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1017 }
1018
Jihoon Kang3c89f042023-12-19 02:40:22 +00001019 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001020 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1021 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1022 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1023 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001024 }
1025
Jihoon Kanga11d6792024-03-05 16:12:20 +00001026 if Bool(d.properties.Annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001027 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001028 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1029 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001030 }
Jihoon Kangee113282024-01-23 00:16:41 +00001031 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1032 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001033 }
Jihoon Kanga11d6792024-03-05 16:12:20 +00001034 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001035 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1036 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001037 }
1038
1039 if params.checkApi || String(d.properties.Api_filename) != "" {
1040 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1041 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1042 }
1043
1044 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1045 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1046 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1047 }
1048
1049 d.optionalStubCmd(ctx, optionalCmdParams)
1050}
1051
1052func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1053
1054 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1055 rule := android.NewRuleBuilder(pctx, ctx)
1056 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1057 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1058 SandboxInputs()
1059
1060 if params.stubConfig.generateStubs {
1061 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1062 }
1063
1064 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1065
1066 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1067
1068 if params.stubConfig.doApiLint {
1069 // Pass the lint baseline file as an input to resolve the lint errors.
1070 // The exportable stubs generation does not update the lint baseline file.
1071 // Lint baseline file update is handled by the everything stubs
1072 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1073 if baselineFile.Valid() {
1074 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1075 }
1076 }
1077
1078 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001079 rule.Command().
1080 BuiltTool("soong_zip").
1081 Flag("-write_if_changed").
1082 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001083 FlagWithOutput("-o ", params.stubsSrcJar).
1084 FlagWithArg("-C ", params.stubsDir.String()).
1085 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001086 }
1087
Jihoon Kang3c89f042023-12-19 02:40:22 +00001088 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001089 rule.Command().
1090 BuiltTool("soong_zip").
1091 Flag("-write_if_changed").
1092 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001093 FlagWithOutput("-o ", params.metadataZip).
1094 FlagWithArg("-C ", params.metadataDir.String()).
1095 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001096 }
1097
Colin Cross6aa5c402021-03-24 12:28:50 -07001098 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001099 if !metalavaUseRbe(ctx) {
1100 rule.Restat()
1101 }
Colin Cross2207f872021-03-24 12:39:08 -07001102
Jihoon Kang3c89f042023-12-19 02:40:22 +00001103 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001104
Jihoon Kang3c89f042023-12-19 02:40:22 +00001105 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1106}
1107
1108func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1109 deps := d.Javadoc.collectDeps(ctx)
1110
1111 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1112 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1113
1114 // Add options for the other optional tasks: API-lint and check-released.
1115 // We generate separate timestamp files for them.
1116 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1117 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1118
1119 writeSdkValues := Bool(d.properties.Write_sdk_values)
1120
1121 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1122
1123 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1124 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1125 String(d.properties.Validate_nullability_from_list) != "")
1126
1127 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1128 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1129
1130 stubCmdParams := stubsCommandConfigParams{
Jihoon Kanga11d6792024-03-05 16:12:20 +00001131 javaVersion: javaVersion,
1132 deps: deps,
1133 checkApi: checkApi,
1134 generateStubs: generateStubs,
1135 doApiLint: doApiLint,
1136 doCheckReleased: doCheckReleased,
1137 writeSdkValues: writeSdkValues,
1138 migratingNullability: migratingNullability,
1139 validatingNullability: validatingNullability,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001140 }
1141 stubCmdParams.stubsType = Everything
1142 // Create default (i.e. "everything" stubs) rule for metalava
1143 d.everythingStubCmd(ctx, stubCmdParams)
1144
Jihoon Kangd40c5912024-03-05 16:12:20 +00001145 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001146 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1147 // strips all flagged apis to generate the "exportable" stubs
1148 stubCmdParams.stubsType = Exportable
1149 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001150
Paul Duffine7a86642022-08-16 15:43:20 +00001151 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1152
1153 if len(d.Javadoc.properties.Out) > 0 {
1154 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1155 }
1156
1157 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1158 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1159 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1160
1161 if baselineFile.Valid() {
1162 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1163 }
1164
Jihoon Kang3c89f042023-12-19 02:40:22 +00001165 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001166
1167 rule := android.NewRuleBuilder(pctx, ctx)
1168
1169 // Diff command line.
1170 // -F matches the closest "opening" line, such as "package android {"
1171 // and " public class Intent {".
1172 diff := `diff -u -F '{ *$'`
1173
1174 rule.Command().Text("( true")
1175 rule.Command().
1176 Text(diff).
1177 Input(apiFile).Input(d.apiFile)
1178
1179 rule.Command().
1180 Text(diff).
1181 Input(removedApiFile).Input(d.removedApiFile)
1182
1183 msg := fmt.Sprintf(`\n******************************\n`+
1184 `You have tried to change the API from what has been previously approved.\n\n`+
1185 `To make these errors go away, you have two choices:\n`+
1186 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1187 ` to the new methods, etc. shown in the above diff.\n\n`+
1188 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1189 ` m %s-update-current-api\n\n`+
1190 ` To submit the revised current.txt to the main Android repository,\n`+
1191 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001192 `If your build failed due to stub validation, you can resolve the errors with\n`+
1193 `either of the two choices above and try re-building the target.\n`+
1194 `If the mismatch between the stubs and the current.txt is intended,\n`+
1195 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001196 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1197 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\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) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001237 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001238 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.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001254 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001255
1256 rule := android.NewRuleBuilder(pctx, ctx)
1257
1258 rule.Command().
1259 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001260 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001261 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 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001270 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001271}
1272
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001273func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1274 api_file := d.properties.Check_api.Current.Api_file
1275 api_surface := d.properties.Api_surface
1276
1277 props := struct {
1278 Name *string
1279 Api_surface *string
1280 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001281 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001282 }{}
1283
1284 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1285 props.Api_surface = api_surface
1286 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001287 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001288
1289 ctx.CreateModule(ApiContributionFactory, &props)
1290}
1291
Spandan Das0b555e32022-11-28 18:48:51 +00001292// TODO (b/262014796): Export the API contributions of CorePlatformApi
1293// A map to populate the api surface of a droidstub from a substring appearing in its name
1294// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1295// use a strict naming convention
1296var (
1297 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1298 //public is commented out since the core libraries use public in their java_sdk_library names
1299 "intracore": android.SdkIntraCore,
1300 "intra.core": android.SdkIntraCore,
1301 "system_server": android.SdkSystemServer,
1302 "system-server": android.SdkSystemServer,
1303 "system": android.SdkSystem,
1304 "module_lib": android.SdkModule,
1305 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001306 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001307 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001308 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001309 }
1310)
1311
Colin Cross2207f872021-03-24 12:39:08 -07001312func StubsDefaultsFactory() android.Module {
1313 module := &DocDefaults{}
1314
1315 module.AddProperties(
1316 &JavadocProperties{},
1317 &DroidstubsProperties{},
1318 )
1319
1320 android.InitDefaultsModule(module)
1321
1322 return module
1323}
1324
1325var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1326
1327type PrebuiltStubsSourcesProperties struct {
1328 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001329
1330 // Name of the source soong module that gets shadowed by this prebuilt
1331 // If unspecified, follows the naming convention that the source module of
1332 // the prebuilt is Name() without "prebuilt_" prefix
1333 Source_module_name *string
1334
1335 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1336 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1337 // (without any prebuilt_ prefix)
1338 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1339}
1340
1341func (j *PrebuiltStubsSources) BaseModuleName() string {
1342 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1343}
1344
1345func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1346 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001347}
1348
1349type PrebuiltStubsSources struct {
1350 android.ModuleBase
1351 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001352 embeddableInModuleAndImport
1353
Colin Cross2207f872021-03-24 12:39:08 -07001354 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001355
1356 properties PrebuiltStubsSourcesProperties
1357
kgui67007242022-01-25 13:50:25 +08001358 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001359}
1360
1361func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1362 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001363 // prebuilt droidstubs does not output "exportable" stubs.
1364 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1365 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001366 return android.Paths{p.stubsSrcJar}, nil
1367 default:
1368 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1369 }
1370}
1371
Jihoon Kangee113282024-01-23 00:16:41 +00001372func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1373 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001374}
1375
1376func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001377 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001378 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 -07001379 return
1380 }
1381
Anton Hansson86758ac2021-11-03 14:44:12 +00001382 src := p.properties.Srcs[0]
1383 if filepath.Ext(src) == ".srcjar" {
1384 // This is a srcjar. We can use it directly.
1385 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1386 } else {
1387 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001388
Anton Hansson86758ac2021-11-03 14:44:12 +00001389 // This is a directory. Glob the contents just in case the directory does not exist.
1390 srcGlob := src + "/**/*"
1391 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001392
Anton Hansson86758ac2021-11-03 14:44:12 +00001393 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1394 // the path components are invalid it won't in this case because no components
1395 // are specified and the module directory must exist in order to get this far.
1396 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001397
Anton Hansson86758ac2021-11-03 14:44:12 +00001398 rule := android.NewRuleBuilder(pctx, ctx)
1399 rule.Command().
1400 BuiltTool("soong_zip").
1401 Flag("-write_if_changed").
1402 Flag("-jar").
1403 FlagWithOutput("-o ", outPath).
1404 FlagWithArg("-C ", srcDir.String()).
1405 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1406 rule.Restat()
1407 rule.Build("zip src", "Create srcjar from prebuilt source")
1408 p.stubsSrcJar = outPath
1409 }
Colin Cross2207f872021-03-24 12:39:08 -07001410}
1411
1412func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1413 return &p.prebuilt
1414}
1415
1416func (p *PrebuiltStubsSources) Name() string {
1417 return p.prebuilt.Name(p.ModuleBase.Name())
1418}
1419
1420// prebuilt_stubs_sources imports a set of java source files as if they were
1421// generated by droidstubs.
1422//
1423// By default, a prebuilt_stubs_sources has a single variant that expects a
1424// set of `.java` files generated by droidstubs.
1425//
1426// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1427// for host modules.
1428//
1429// Intended only for use by sdk snapshots.
1430func PrebuiltStubsSourcesFactory() android.Module {
1431 module := &PrebuiltStubsSources{}
1432
1433 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001434 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001435
1436 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001437 InitDroiddocModule(module, android.HostAndDeviceSupported)
1438 return module
1439}