blob: 6ca59d1dbb8d1c3dc718f3e554f9eebb262d56e6 [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 Kang6b93b382024-01-26 22:37:41 +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
242 annotationsEnabled bool
243 apiLevelsAnnotationsEnabled bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000244}
245
Colin Cross2207f872021-03-24 12:39:08 -0700246// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
247// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
248// a droiddoc module to generate documentation.
249func DroidstubsFactory() android.Module {
250 module := &Droidstubs{}
251
252 module.AddProperties(&module.properties,
253 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000254 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700255
256 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000257
258 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
259 module.createApiContribution(ctx)
260 })
Colin Cross2207f872021-03-24 12:39:08 -0700261 return module
262}
263
264// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
265// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
266// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
267// module when symbols needed by the source files are provided by java_library_host modules.
268func DroidstubsHostFactory() android.Module {
269 module := &Droidstubs{}
270
271 module.AddProperties(&module.properties,
272 &module.Javadoc.properties)
273
274 InitDroiddocModule(module, android.HostSupported)
275 return module
276}
277
Jihoon Kang78f89142023-12-27 01:40:29 +0000278func getStubsTypeAndTag(tag string) (StubsType, string, error) {
279 if len(tag) == 0 {
280 return Everything, "", nil
281 }
282 if tag[0] != '.' {
283 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
284 }
285
286 stubsType := Everything
287 // Check if the tag has a stubs type prefix (e.g. ".exportable")
288 for st := Everything; st <= Exportable; st++ {
289 if strings.HasPrefix(tag, "."+st.String()) {
290 stubsType = st
291 }
292 }
293
294 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
295}
296
297// Droidstubs' tag supports specifying with the stubs type.
298// While supporting the pre-existing tags, it also supports tags with
299// the stubs type prefix. Some examples are shown below:
300// {.annotations.zip} - pre-existing behavior. Returns the path to the
301// annotation zip.
302// {.exportable} - Returns the path to the exportable stubs src jar.
303// {.exportable.annotations.zip} - Returns the path to the exportable
304// annotations zip file.
305// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
306// xml file. For unsupported combinations, the default everything output file
307// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700308func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000309 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
310 if err != nil {
311 return nil, err
312 }
313 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700314 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000315 stubsSrcJar, err := d.StubsSrcJar(stubsType)
316 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700317 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000318 docZip, err := d.DocZip(stubsType)
319 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700320 case ".api.txt", android.DefaultDistTag:
321 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000322 apiFilePath, err := d.ApiFilePath(stubsType)
323 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700324 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000325 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
326 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700327 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000328 annotationsZip, err := d.AnnotationsZip(stubsType)
329 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700330 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000331 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
332 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700333 default:
334 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
335 }
336}
337
Jihoon Kang246690a2024-02-01 21:55:01 +0000338func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000339 switch stubsType {
340 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000341 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000342 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000343 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000344 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000345 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000346 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000347 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000348}
349
Jihoon Kang246690a2024-02-01 21:55:01 +0000350func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000351 switch stubsType {
352 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000353 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000354 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000355 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000356 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000357 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000358 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000359 if ret == nil && err == nil {
360 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
361 }
362 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000363}
364
Jihoon Kang246690a2024-02-01 21:55:01 +0000365func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000366 switch stubsType {
367 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000368 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000369 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000371 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 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 +0000373 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000374 if ret == nil && err == nil {
375 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
376 }
377 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000378}
379
Jihoon Kang246690a2024-02-01 21:55:01 +0000380func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000381 switch stubsType {
382 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000383 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000384 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000386 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000387 if ret == nil && err == nil {
388 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
389 }
390 return ret, err
391}
392
393func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
394 switch stubsType {
395 case Everything:
396 ret, err = d.removedApiFile, nil
397 case Exportable:
398 ret, err = d.exportableRemovedApiFile, nil
399 default:
400 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
401 }
402 if ret == nil && err == nil {
403 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
404 }
405 return ret, err
406}
407
408func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
409 switch stubsType {
410 case Everything:
411 ret, err = d.stubsSrcJar, nil
412 case Exportable:
413 ret, err = d.exportableStubsSrcJar, nil
414 default:
415 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
416 }
417 if ret == nil && err == nil {
418 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
419 }
420 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000421}
422
Jihoon Kang063ec002023-06-28 01:16:23 +0000423func (d *Droidstubs) CurrentApiTimestamp() android.Path {
424 return d.checkCurrentApiTimestamp
425}
426
Colin Cross2207f872021-03-24 12:39:08 -0700427var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
428var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
429var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000430var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000431var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700432
433func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
434 d.Javadoc.addDeps(ctx)
435
436 if len(d.properties.Merge_annotations_dirs) != 0 {
437 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
438 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
439 }
440 }
441
442 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
443 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
444 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
445 }
446 }
447
448 if len(d.properties.Api_levels_annotations_dirs) != 0 {
449 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
450 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
451 }
452 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000453
Jihoon Kang6592e872023-12-19 01:13:16 +0000454 if len(d.properties.Aconfig_declarations) != 0 {
455 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
456 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
457 }
458 }
459
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000460 if d.properties.Api_levels_module != nil {
461 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
462 }
Colin Cross2207f872021-03-24 12:39:08 -0700463}
464
Jihoon Kang3c89f042023-12-19 02:40:22 +0000465func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
466 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
467}
468
469func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
470 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700471 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000472 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000473 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000474
475 if stubsType == Everything {
476 d.apiFile = uncheckedApiFile
477 } else if stubsType == Exportable {
478 d.exportableApiFile = uncheckedApiFile
479 }
Colin Cross2207f872021-03-24 12:39:08 -0700480 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
481 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000482 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700483 }
484
Jihoon Kang3c89f042023-12-19 02:40:22 +0000485 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700486 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000488 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000489
490 if stubsType == Everything {
491 d.removedApiFile = uncheckedRemovedFile
492 } else if stubsType == Exportable {
493 d.exportableRemovedApiFile = uncheckedRemovedFile
494 }
Colin Cross2207f872021-03-24 12:39:08 -0700495 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
496 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000497 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700498 }
499
Colin Cross2207f872021-03-24 12:39:08 -0700500 if stubsDir.Valid() {
501 if Bool(d.properties.Create_doc_stubs) {
502 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
503 } else {
504 cmd.FlagWithArg("--stubs ", stubsDir.String())
505 if !Bool(d.properties.Output_javadoc_comments) {
506 cmd.Flag("--exclude-documentation-from-stubs")
507 }
508 }
509 }
510}
511
Jihoon Kang3c89f042023-12-19 02:40:22 +0000512func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kang6b93b382024-01-26 22:37:41 +0000513 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100514
Jihoon Kang6b93b382024-01-26 22:37:41 +0000515 if params.migratingNullability {
516 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
517 cmd.FlagWithInput("--migrate-nullness ", previousApi)
Colin Cross2207f872021-03-24 12:39:08 -0700518 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000519
520 if s := String(d.properties.Validate_nullability_from_list); s != "" {
521 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
522 }
523
524 if params.validatingNullability {
525 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
526 }
527
Jihoon Kangd40c5912024-03-05 16:12:20 +0000528 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000529
530 if len(d.properties.Merge_annotations_dirs) != 0 {
531 d.mergeAnnoDirFlags(ctx, cmd)
532 }
533
534 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700535}
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 Kang6b93b382024-01-26 22:37:41 +0000559func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000560 var apiVersions android.Path
Jihoon Kang6b93b382024-01-26 22:37:41 +0000561 stubsType := params.stubConfig.stubsType
562 apiVersionsXml := params.apiVersionsXml
563 if params.stubConfig.apiLevelsAnnotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000564 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000565 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000566 } else {
567 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
568 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000569 if stubsType == Everything {
570 apiVersions = s.everythingArtifacts.apiVersionsXml
571 } else if stubsType == Exportable {
572 apiVersions = s.exportableArtifacts.apiVersionsXml
573 } else {
Jihoon Kangd40c5912024-03-05 16:12:20 +0000574 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
Jihoon Kangd9a06942024-01-26 01:49:20 +0000575 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000576 } else {
577 ctx.PropertyErrorf("api_levels_module",
578 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
579 }
580 })
Colin Cross2207f872021-03-24 12:39:08 -0700581 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000582 if apiVersions != nil {
583 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
584 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
585 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
586 }
587}
Colin Cross2207f872021-03-24 12:39:08 -0700588
Jihoon Kang3c89f042023-12-19 02:40:22 +0000589func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700590 if len(d.properties.Api_levels_annotations_dirs) == 0 {
591 ctx.PropertyErrorf("api_levels_annotations_dirs",
592 "has to be non-empty if api levels annotations was enabled!")
593 }
594
Jihoon Kang3c89f042023-12-19 02:40:22 +0000595 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700596
597 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
598
satayev783195c2021-06-23 21:49:57 +0100599 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200600 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700601 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
602 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200603 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
604
605 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
606 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700607 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200608 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
609 if extensions_dir == "" {
610 extensions_dir = t.dir.String() + "/extensions"
611 }
612 cmd.Implicit(dep)
613 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700614 if dep.Base() == filename {
615 cmd.Implicit(dep)
616 }
617 if filename != "android.jar" && dep.Base() == "android.jar" {
618 // Metalava implicitly searches these patterns:
619 // prebuilts/tools/common/api-versions/android-%/android.jar
620 // prebuilts/sdk/%/public/android.jar
621 // Add android.jar files from the api_levels_annotations_dirs directories to try
622 // to satisfy these patterns. If Metalava can't find a match for an API level
623 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700624 cmd.Implicit(dep)
625 }
626 }
satayev783195c2021-06-23 21:49:57 +0100627
628 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700629 } else {
630 ctx.PropertyErrorf("api_levels_annotations_dirs",
631 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
632 }
633 })
satayev783195c2021-06-23 21:49:57 +0100634
635 // Add all relevant --android-jar-pattern patterns for Metalava.
636 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
637 // an actual file present on disk (in the order the patterns were passed). For system APIs for
638 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000639 // for older releases. Similarly, module-lib falls back to system API.
640 var sdkDirs []string
641 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700642 case "system-server":
643 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000644 case "module-lib":
645 sdkDirs = []string{"module-lib", "system", "public"}
646 case "system":
647 sdkDirs = []string{"system", "public"}
648 case "public":
649 sdkDirs = []string{"public"}
650 default:
651 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
652 return
satayev783195c2021-06-23 21:49:57 +0100653 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000654
655 for _, sdkDir := range sdkDirs {
656 for _, dir := range dirs {
657 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
658 }
satayev783195c2021-06-23 21:49:57 +0100659 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200660
661 if d.properties.Extensions_info_file != nil {
662 if extensions_dir == "" {
663 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
664 }
665 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
666 cmd.Implicit(info_file)
667 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
668 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
669 }
Colin Cross2207f872021-03-24 12:39:08 -0700670}
671
Colin Crosse52c2ac2022-03-28 17:03:35 -0700672func metalavaUseRbe(ctx android.ModuleContext) bool {
673 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
674}
675
Colin Cross2207f872021-03-24 12:39:08 -0700676func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100677 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700678 rule.Command().Text("rm -rf").Flag(homeDir.String())
679 rule.Command().Text("mkdir -p").Flag(homeDir.String())
680
Anton Hansson556e8142021-06-04 16:20:25 +0100681 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700682 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
683
Colin Crosse52c2ac2022-03-28 17:03:35 -0700684 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700685 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700686 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000687 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
688 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700689 labels := map[string]string{"type": "tool", "name": "metalava"}
690 // TODO: metalava pool rejects these jobs
691 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
692 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000693 Labels: labels,
694 ExecStrategy: execStrategy,
695 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
696 Platform: map[string]string{remoteexec.PoolKey: pool},
697 Compare: compare,
698 NumLocalRuns: 1,
699 NumRemoteRuns: 1,
700 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700701 })
Colin Cross2207f872021-03-24 12:39:08 -0700702 }
703
Colin Cross6aa5c402021-03-24 12:28:50 -0700704 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700705 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400706 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100707 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700708 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
709 FlagWithInput("@", srcJarList)
710
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100711 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
712 // years, so it is unlikely to change any time soon.
713 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
714 combinedPaths = append(combinedPaths, classpath.Paths()...)
715 if len(combinedPaths) > 0 {
716 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700717 }
718
Liz Kammere09e20e2023-10-16 15:07:54 -0400719 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000720
Colin Cross2207f872021-03-24 12:39:08 -0700721 return cmd
722}
723
Jihoon Kang3c89f042023-12-19 02:40:22 +0000724// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
725// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
726// property is defined, apply transformations and only revert the flagged apis that are not
727// enabled via release configurations and are not specified in aconfig_declarations
728func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
729
730 if len(aconfigFlagsPaths) == 0 {
731 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
732 return
733 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000734
735 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
736 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
737
738 var filterArgs string
739 switch stubsType {
740 // No flagged apis specific flags need to be passed to metalava when generating
741 // everything stubs
742 case Everything:
743 return
744
745 case Runtime:
746 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
747
748 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000749 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
750 // the flagged apis that have read_write permissions are exposed on top of the enabled
751 // and read_only apis. This is to support local override of flag values at runtime.
752 if ctx.Config().ReleaseExportRuntimeApis() {
753 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
754 } else {
755 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
756 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000757 }
758
759 ctx.Build(pctx, android.BuildParams{
760 Rule: gatherReleasedFlaggedApisRule,
761 Inputs: aconfigFlagsPaths,
762 Output: releasedFlaggedApisFile,
763 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
764 Args: map[string]string{
765 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
766 "filter_args": filterArgs,
767 },
768 })
769
770 ctx.Build(pctx, android.BuildParams{
771 Rule: generateMetalavaRevertAnnotationsRule,
772 Input: releasedFlaggedApisFile,
773 Output: revertAnnotationsFile,
774 Description: fmt.Sprintf("%s revert annotations", stubsType),
775 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000776
777 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000778}
779
Jihoon Kang3c89f042023-12-19 02:40:22 +0000780func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
781 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700782 if BoolDefault(d.properties.High_mem, false) {
783 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
784 rule.HighMem()
785 }
786
Jihoon Kang3c89f042023-12-19 02:40:22 +0000787 if params.stubConfig.generateStubs {
788 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
789 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700790 }
791
Jihoon Kang3c89f042023-12-19 02:40:22 +0000792 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700793
Jihoon Kang3c89f042023-12-19 02:40:22 +0000794 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
795 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
796 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700797 cmd.Implicits(d.Javadoc.implicits)
798
Jihoon Kang3c89f042023-12-19 02:40:22 +0000799 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700800
Jihoon Kang3c89f042023-12-19 02:40:22 +0000801 if params.stubConfig.writeSdkValues {
802 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
803 }
804
805 annotationParams := annotationFlagsParams{
806 migratingNullability: params.stubConfig.migratingNullability,
807 validatingNullability: params.stubConfig.validatingNullability,
808 nullabilityWarningsFile: params.nullabilityWarningsFile,
809 annotationsZip: params.annotationsZip,
810 }
811
Jihoon Kang6b93b382024-01-26 22:37:41 +0000812 if params.stubConfig.annotationsEnabled {
813 d.annotationsFlags(ctx, cmd, annotationParams)
814 }
Colin Cross2207f872021-03-24 12:39:08 -0700815 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000816 d.apiLevelsAnnotationsFlags(ctx, cmd, params)
Colin Cross2207f872021-03-24 12:39:08 -0700817
Colin Crossbc139922021-03-25 18:33:16 -0700818 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700819
Colin Cross2207f872021-03-24 12:39:08 -0700820 for _, o := range d.Javadoc.properties.Out {
821 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
822 }
823
Jihoon Kang3c89f042023-12-19 02:40:22 +0000824 return cmd
825}
Colin Cross2207f872021-03-24 12:39:08 -0700826
Jihoon Kang3c89f042023-12-19 02:40:22 +0000827// Sandbox rule for generating the everything stubs and other artifacts
828func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
829 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
830 rule := android.NewRuleBuilder(pctx, ctx)
831 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
832 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
833 SandboxInputs()
834
835 var stubsDir android.OptionalPath
836 if params.generateStubs {
837 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
838 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
839 }
840
841 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000842 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
843 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000844 }
845
Jihoon Kang6b93b382024-01-26 22:37:41 +0000846 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000847 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000848 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000849 }
Jihoon Kangee113282024-01-23 00:16:41 +0000850 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000851 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000852 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +0000853 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000854 }
855
856 commonCmdParams := stubsCommandParams{
857 srcJarDir: srcJarDir,
858 stubsDir: stubsDir,
859 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000860 metadataDir: d.everythingArtifacts.metadataDir,
861 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
862 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
863 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000864 stubConfig: params,
865 }
866
867 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
868
869 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
870
871 if params.generateStubs {
872 rule.Command().
873 BuiltTool("soong_zip").
874 Flag("-write_if_changed").
875 Flag("-jar").
876 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
877 FlagWithArg("-C ", stubsDir.String()).
878 FlagWithArg("-D ", stubsDir.String())
879 }
880
881 if params.writeSdkValues {
882 rule.Command().
883 BuiltTool("soong_zip").
884 Flag("-write_if_changed").
885 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000886 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
887 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
888 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000889 }
890
891 // TODO: We don't really need two separate API files, but this is a reminiscence of how
892 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
893 if params.doApiLint {
894 rule.Command().Text("touch").Output(d.apiLintTimestamp)
895 }
896 if params.doCheckReleased {
897 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
898 }
899
900 // TODO(b/183630617): rewrapper doesn't support restat rules
901 if !metalavaUseRbe(ctx) {
902 rule.Restat()
903 }
904
905 zipSyncCleanupCmd(rule, srcJarDir)
906
907 rule.Build("metalava", "metalava merged")
908}
909
910// Sandbox rule for generating the everything artifacts that are not run by
911// default but only run based on the module configurations
912func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700913
914 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000915 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700916 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
917 if newSince.Valid() {
918 cmd.FlagWithInput("--api-lint ", newSince.Path())
919 } else {
920 cmd.Flag("--api-lint")
921 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000922 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700923 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
924
Colin Cross0d532412021-03-25 09:38:45 -0700925 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700926 if d.Name() != "android.car-system-stubs-docs" &&
927 d.Name() != "android.car-stubs-docs" {
928 cmd.Flag("--lints-as-errors")
929 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
930 }
931
932 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000933 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
934 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700935
936 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700937 //
938 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
939 // message and metalava's one?
940 msg := `$'` + // Enclose with $' ... '
941 `************************************************************\n` +
942 `Your API changes are triggering API Lint warnings or errors.\n` +
943 `To make these errors go away, fix the code according to the\n` +
944 `error and/or warning messages above.\n` +
945 `\n` +
946 `If it is not possible to do so, there are workarounds:\n` +
947 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000948 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
949 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700950
951 if baselineFile.Valid() {
952 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
953 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
954
955 msg += fmt.Sprintf(``+
956 `2. You can update the baseline by executing the following\n`+
957 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700958 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
959 ` "%s" \\\n`+
960 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700961 ` To submit the revised baseline.txt to the main Android\n`+
962 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
963 } else {
964 msg += fmt.Sprintf(``+
965 `2. You can add a baseline file of existing lint failures\n`+
966 ` to the build rule of %s.\n`, d.Name())
967 }
968 // Note the message ends with a ' (single quote), to close the $' ... ' .
969 msg += `************************************************************\n'`
970
971 cmd.FlagWithArg("--error-message:api-lint ", msg)
972 }
973
974 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000975 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700976 if len(d.Javadoc.properties.Out) > 0 {
977 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
978 }
979
980 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
981 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
982 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000983 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700984
Jihoon Kang3c89f042023-12-19 02:40:22 +0000985 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700986
987 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
988 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
989
990 if baselineFile.Valid() {
991 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
992 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
993 }
994
995 // Note this string includes quote ($' ... '), which decodes the "\n"s.
996 msg := `$'\n******************************\n` +
997 `You have tried to change the API from what has been previously released in\n` +
998 `an SDK. Please fix the errors listed above.\n` +
999 `******************************\n'`
1000
1001 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1002 }
1003
Paul Duffin10a23c22023-08-11 22:47:31 +01001004 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1005 // Pass the current API file into metalava so it can use it as the basis for determining how to
1006 // generate the output signature files (both api and removed).
1007 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1008 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1009 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001010}
Paul Duffin10a23c22023-08-11 22:47:31 +01001011
Jihoon Kang3c89f042023-12-19 02:40:22 +00001012// Sandbox rule for generating exportable stubs and other artifacts
1013func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1014 optionalCmdParams := stubsCommandParams{
1015 stubConfig: params,
1016 }
1017
Jihoon Kang246690a2024-02-01 21:55:01 +00001018 if params.generateStubs {
1019 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1020 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1021 }
1022
Jihoon Kang3c89f042023-12-19 02:40:22 +00001023 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001024 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1025 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1026 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1027 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001028 }
1029
Jihoon Kang6b93b382024-01-26 22:37:41 +00001030 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001031 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001032 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1033 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001034 }
Jihoon Kangee113282024-01-23 00:16:41 +00001035 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1036 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001037 }
Jihoon Kang6b93b382024-01-26 22:37:41 +00001038 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +00001039 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1040 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001041 }
1042
1043 if params.checkApi || String(d.properties.Api_filename) != "" {
1044 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1045 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1046 }
1047
1048 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1049 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1050 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1051 }
1052
1053 d.optionalStubCmd(ctx, optionalCmdParams)
1054}
1055
1056func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1057
1058 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1059 rule := android.NewRuleBuilder(pctx, ctx)
1060 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1061 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1062 SandboxInputs()
1063
1064 if params.stubConfig.generateStubs {
1065 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1066 }
1067
1068 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1069
1070 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1071
1072 if params.stubConfig.doApiLint {
1073 // Pass the lint baseline file as an input to resolve the lint errors.
1074 // The exportable stubs generation does not update the lint baseline file.
1075 // Lint baseline file update is handled by the everything stubs
1076 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1077 if baselineFile.Valid() {
1078 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1079 }
1080 }
1081
1082 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001083 rule.Command().
1084 BuiltTool("soong_zip").
1085 Flag("-write_if_changed").
1086 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001087 FlagWithOutput("-o ", params.stubsSrcJar).
1088 FlagWithArg("-C ", params.stubsDir.String()).
1089 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001090 }
1091
Jihoon Kang3c89f042023-12-19 02:40:22 +00001092 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001093 rule.Command().
1094 BuiltTool("soong_zip").
1095 Flag("-write_if_changed").
1096 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001097 FlagWithOutput("-o ", params.metadataZip).
1098 FlagWithArg("-C ", params.metadataDir.String()).
1099 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001100 }
1101
Colin Cross6aa5c402021-03-24 12:28:50 -07001102 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001103 if !metalavaUseRbe(ctx) {
1104 rule.Restat()
1105 }
Colin Cross2207f872021-03-24 12:39:08 -07001106
Jihoon Kang3c89f042023-12-19 02:40:22 +00001107 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001108
Jihoon Kang3c89f042023-12-19 02:40:22 +00001109 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1110}
1111
1112func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1113 deps := d.Javadoc.collectDeps(ctx)
1114
1115 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1116 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1117
1118 // Add options for the other optional tasks: API-lint and check-released.
1119 // We generate separate timestamp files for them.
1120 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1121 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1122
1123 writeSdkValues := Bool(d.properties.Write_sdk_values)
1124
1125 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1126
1127 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1128 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1129 String(d.properties.Validate_nullability_from_list) != "")
1130
1131 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1132 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1133
Jihoon Kang6b93b382024-01-26 22:37:41 +00001134 apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
1135
Jihoon Kang3c89f042023-12-19 02:40:22 +00001136 stubCmdParams := stubsCommandConfigParams{
Jihoon Kang6b93b382024-01-26 22:37:41 +00001137 javaVersion: javaVersion,
1138 deps: deps,
1139 checkApi: checkApi,
1140 generateStubs: generateStubs,
1141 doApiLint: doApiLint,
1142 doCheckReleased: doCheckReleased,
1143 writeSdkValues: writeSdkValues,
1144 migratingNullability: migratingNullability,
1145 validatingNullability: validatingNullability,
1146 annotationsEnabled: annotationsEnabled,
1147 apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001148 }
1149 stubCmdParams.stubsType = Everything
1150 // Create default (i.e. "everything" stubs) rule for metalava
1151 d.everythingStubCmd(ctx, stubCmdParams)
1152
Jihoon Kangd40c5912024-03-05 16:12:20 +00001153 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001154 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1155 // strips all flagged apis to generate the "exportable" stubs
1156 stubCmdParams.stubsType = Exportable
1157 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001158
Paul Duffine7a86642022-08-16 15:43:20 +00001159 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1160
1161 if len(d.Javadoc.properties.Out) > 0 {
1162 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1163 }
1164
1165 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1166 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1167 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1168
1169 if baselineFile.Valid() {
1170 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1171 }
1172
Jihoon Kang3c89f042023-12-19 02:40:22 +00001173 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001174
1175 rule := android.NewRuleBuilder(pctx, ctx)
1176
1177 // Diff command line.
1178 // -F matches the closest "opening" line, such as "package android {"
1179 // and " public class Intent {".
1180 diff := `diff -u -F '{ *$'`
1181
1182 rule.Command().Text("( true")
1183 rule.Command().
1184 Text(diff).
1185 Input(apiFile).Input(d.apiFile)
1186
1187 rule.Command().
1188 Text(diff).
1189 Input(removedApiFile).Input(d.removedApiFile)
1190
1191 msg := fmt.Sprintf(`\n******************************\n`+
1192 `You have tried to change the API from what has been previously approved.\n\n`+
1193 `To make these errors go away, you have two choices:\n`+
1194 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1195 ` to the new methods, etc. shown in the above diff.\n\n`+
1196 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1197 ` m %s-update-current-api\n\n`+
1198 ` To submit the revised current.txt to the main Android repository,\n`+
1199 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001200 `If your build failed due to stub validation, you can resolve the errors with\n`+
1201 `either of the two choices above and try re-building the target.\n`+
1202 `If the mismatch between the stubs and the current.txt is intended,\n`+
1203 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001204 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1205 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001206 `******************************\n`, ctx.ModuleName())
1207
1208 rule.Command().
1209 Text("touch").Output(d.checkCurrentApiTimestamp).
1210 Text(") || (").
1211 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1212 Text("; exit 38").
1213 Text(")")
1214
1215 rule.Build("metalavaCurrentApiCheck", "check current API")
1216
Jihoon Kang3c89f042023-12-19 02:40:22 +00001217 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001218
1219 // update API rule
1220 rule = android.NewRuleBuilder(pctx, ctx)
1221
1222 rule.Command().Text("( true")
1223
1224 rule.Command().
1225 Text("cp").Flag("-f").
1226 Input(d.apiFile).Flag(apiFile.String())
1227
1228 rule.Command().
1229 Text("cp").Flag("-f").
1230 Input(d.removedApiFile).Flag(removedApiFile.String())
1231
1232 msg = "failed to update public API"
1233
1234 rule.Command().
1235 Text("touch").Output(d.updateCurrentApiTimestamp).
1236 Text(") || (").
1237 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1238 Text("; exit 38").
1239 Text(")")
1240
1241 rule.Build("metalavaCurrentApiUpdate", "update current API")
1242 }
1243
Colin Cross2207f872021-03-24 12:39:08 -07001244 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001245 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001246 ctx.PropertyErrorf("check_nullability_warnings",
1247 "Cannot specify check_nullability_warnings unless validating nullability")
1248 }
1249
1250 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1251
Jihoon Kang3c89f042023-12-19 02:40:22 +00001252 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001253
1254 msg := fmt.Sprintf(`\n******************************\n`+
1255 `The warnings encountered during nullability annotation validation did\n`+
1256 `not match the checked in file of expected warnings. The diffs are shown\n`+
1257 `above. You have two options:\n`+
1258 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1259 ` 2. Update the file of expected warnings by running:\n`+
1260 ` cp %s %s\n`+
1261 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001262 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001263
1264 rule := android.NewRuleBuilder(pctx, ctx)
1265
1266 rule.Command().
1267 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001268 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001269 Text("&&").
1270 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1271 Text(") || (").
1272 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1273 Text("; exit 38").
1274 Text(")")
1275
1276 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1277 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001278 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001279}
1280
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001281func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1282 api_file := d.properties.Check_api.Current.Api_file
1283 api_surface := d.properties.Api_surface
1284
1285 props := struct {
1286 Name *string
1287 Api_surface *string
1288 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001289 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001290 }{}
1291
1292 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1293 props.Api_surface = api_surface
1294 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001295 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001296
1297 ctx.CreateModule(ApiContributionFactory, &props)
1298}
1299
Spandan Das0b555e32022-11-28 18:48:51 +00001300// TODO (b/262014796): Export the API contributions of CorePlatformApi
1301// A map to populate the api surface of a droidstub from a substring appearing in its name
1302// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1303// use a strict naming convention
1304var (
1305 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1306 //public is commented out since the core libraries use public in their java_sdk_library names
1307 "intracore": android.SdkIntraCore,
1308 "intra.core": android.SdkIntraCore,
1309 "system_server": android.SdkSystemServer,
1310 "system-server": android.SdkSystemServer,
1311 "system": android.SdkSystem,
1312 "module_lib": android.SdkModule,
1313 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001314 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001315 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001316 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001317 }
1318)
1319
Colin Cross2207f872021-03-24 12:39:08 -07001320func StubsDefaultsFactory() android.Module {
1321 module := &DocDefaults{}
1322
1323 module.AddProperties(
1324 &JavadocProperties{},
1325 &DroidstubsProperties{},
1326 )
1327
1328 android.InitDefaultsModule(module)
1329
1330 return module
1331}
1332
1333var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1334
1335type PrebuiltStubsSourcesProperties struct {
1336 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001337
1338 // Name of the source soong module that gets shadowed by this prebuilt
1339 // If unspecified, follows the naming convention that the source module of
1340 // the prebuilt is Name() without "prebuilt_" prefix
1341 Source_module_name *string
1342
1343 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1344 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1345 // (without any prebuilt_ prefix)
1346 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1347}
1348
1349func (j *PrebuiltStubsSources) BaseModuleName() string {
1350 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1351}
1352
1353func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1354 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001355}
1356
1357type PrebuiltStubsSources struct {
1358 android.ModuleBase
1359 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001360 embeddableInModuleAndImport
1361
Colin Cross2207f872021-03-24 12:39:08 -07001362 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001363
1364 properties PrebuiltStubsSourcesProperties
1365
kgui67007242022-01-25 13:50:25 +08001366 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001367}
1368
1369func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1370 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001371 // prebuilt droidstubs does not output "exportable" stubs.
1372 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1373 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001374 return android.Paths{p.stubsSrcJar}, nil
1375 default:
1376 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1377 }
1378}
1379
Jihoon Kangee113282024-01-23 00:16:41 +00001380func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1381 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001382}
1383
1384func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001385 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001386 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 -07001387 return
1388 }
1389
Anton Hansson86758ac2021-11-03 14:44:12 +00001390 src := p.properties.Srcs[0]
1391 if filepath.Ext(src) == ".srcjar" {
1392 // This is a srcjar. We can use it directly.
1393 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1394 } else {
1395 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001396
Anton Hansson86758ac2021-11-03 14:44:12 +00001397 // This is a directory. Glob the contents just in case the directory does not exist.
1398 srcGlob := src + "/**/*"
1399 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001400
Anton Hansson86758ac2021-11-03 14:44:12 +00001401 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1402 // the path components are invalid it won't in this case because no components
1403 // are specified and the module directory must exist in order to get this far.
1404 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001405
Anton Hansson86758ac2021-11-03 14:44:12 +00001406 rule := android.NewRuleBuilder(pctx, ctx)
1407 rule.Command().
1408 BuiltTool("soong_zip").
1409 Flag("-write_if_changed").
1410 Flag("-jar").
1411 FlagWithOutput("-o ", outPath).
1412 FlagWithArg("-C ", srcDir.String()).
1413 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1414 rule.Restat()
1415 rule.Build("zip src", "Create srcjar from prebuilt source")
1416 p.stubsSrcJar = outPath
1417 }
Colin Cross2207f872021-03-24 12:39:08 -07001418}
1419
1420func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1421 return &p.prebuilt
1422}
1423
1424func (p *PrebuiltStubsSources) Name() string {
1425 return p.prebuilt.Name(p.ModuleBase.Name())
1426}
1427
1428// prebuilt_stubs_sources imports a set of java source files as if they were
1429// generated by droidstubs.
1430//
1431// By default, a prebuilt_stubs_sources has a single variant that expects a
1432// set of `.java` files generated by droidstubs.
1433//
1434// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1435// for host modules.
1436//
1437// Intended only for use by sdk snapshots.
1438func PrebuiltStubsSourcesFactory() android.Module {
1439 module := &PrebuiltStubsSources{}
1440
1441 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001442 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001443
1444 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001445 InitDroiddocModule(module, android.HostAndDeviceSupported)
1446 return module
1447}