blob: b1126146caad7e296efe97e9aaffb71fe9a59e5a [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
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000217 extractAnnotations bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000218 nullabilityWarningsFile android.WritablePath
219 annotationsZip android.WritablePath
220}
221type stubsCommandParams struct {
222 srcJarDir android.ModuleOutPath
223 stubsDir android.OptionalPath
224 stubsSrcJar android.WritablePath
225 metadataZip android.WritablePath
226 metadataDir android.WritablePath
227 apiVersionsXml android.WritablePath
228 nullabilityWarningsFile android.WritablePath
229 annotationsZip android.WritablePath
230 stubConfig stubsCommandConfigParams
231}
232type stubsCommandConfigParams struct {
Jihoon Kang6b93b382024-01-26 22:37:41 +0000233 stubsType StubsType
234 javaVersion javaVersion
235 deps deps
236 checkApi bool
237 generateStubs bool
238 doApiLint bool
239 doCheckReleased bool
240 writeSdkValues bool
241 migratingNullability bool
242 validatingNullability bool
243 annotationsEnabled bool
244 apiLevelsAnnotationsEnabled bool
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000245 extractAnnotations bool
Jihoon Kang3c89f042023-12-19 02:40:22 +0000246}
247
Colin Cross2207f872021-03-24 12:39:08 -0700248// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
249// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
250// a droiddoc module to generate documentation.
251func DroidstubsFactory() android.Module {
252 module := &Droidstubs{}
253
254 module.AddProperties(&module.properties,
255 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000256 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700257
258 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000259
260 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
261 module.createApiContribution(ctx)
262 })
Colin Cross2207f872021-03-24 12:39:08 -0700263 return module
264}
265
266// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
267// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
268// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
269// module when symbols needed by the source files are provided by java_library_host modules.
270func DroidstubsHostFactory() android.Module {
271 module := &Droidstubs{}
272
273 module.AddProperties(&module.properties,
274 &module.Javadoc.properties)
275
276 InitDroiddocModule(module, android.HostSupported)
277 return module
278}
279
Jihoon Kang78f89142023-12-27 01:40:29 +0000280func getStubsTypeAndTag(tag string) (StubsType, string, error) {
281 if len(tag) == 0 {
282 return Everything, "", nil
283 }
284 if tag[0] != '.' {
285 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
286 }
287
288 stubsType := Everything
289 // Check if the tag has a stubs type prefix (e.g. ".exportable")
290 for st := Everything; st <= Exportable; st++ {
291 if strings.HasPrefix(tag, "."+st.String()) {
292 stubsType = st
293 }
294 }
295
296 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
297}
298
299// Droidstubs' tag supports specifying with the stubs type.
300// While supporting the pre-existing tags, it also supports tags with
301// the stubs type prefix. Some examples are shown below:
302// {.annotations.zip} - pre-existing behavior. Returns the path to the
303// annotation zip.
304// {.exportable} - Returns the path to the exportable stubs src jar.
305// {.exportable.annotations.zip} - Returns the path to the exportable
306// annotations zip file.
307// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
308// xml file. For unsupported combinations, the default everything output file
309// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700310func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000311 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
312 if err != nil {
313 return nil, err
314 }
315 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700316 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000317 stubsSrcJar, err := d.StubsSrcJar(stubsType)
318 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700319 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000320 docZip, err := d.DocZip(stubsType)
321 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700322 case ".api.txt", android.DefaultDistTag:
323 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000324 apiFilePath, err := d.ApiFilePath(stubsType)
325 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700326 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000327 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
328 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700329 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000330 annotationsZip, err := d.AnnotationsZip(stubsType)
331 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700332 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000333 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
334 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700335 default:
336 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
337 }
338}
339
Jihoon Kang246690a2024-02-01 21:55:01 +0000340func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000341 switch stubsType {
342 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000343 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000344 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000345 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000346 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000347 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000348 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000349 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000350}
351
Jihoon Kang246690a2024-02-01 21:55:01 +0000352func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000353 switch stubsType {
354 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000355 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000356 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000357 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000358 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000359 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000360 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000361 if ret == nil && err == nil {
362 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
363 }
364 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000365}
366
Jihoon Kang246690a2024-02-01 21:55:01 +0000367func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000368 switch stubsType {
369 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000371 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000373 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000374 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 +0000375 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000376 if ret == nil && err == nil {
377 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
378 }
379 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000380}
381
Jihoon Kang246690a2024-02-01 21:55:01 +0000382func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000383 switch stubsType {
384 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000386 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000387 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000388 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000389 if ret == nil && err == nil {
390 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
391 }
392 return ret, err
393}
394
395func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
396 switch stubsType {
397 case Everything:
398 ret, err = d.removedApiFile, nil
399 case Exportable:
400 ret, err = d.exportableRemovedApiFile, nil
401 default:
402 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
403 }
404 if ret == nil && err == nil {
405 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
406 }
407 return ret, err
408}
409
410func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
411 switch stubsType {
412 case Everything:
413 ret, err = d.stubsSrcJar, nil
414 case Exportable:
415 ret, err = d.exportableStubsSrcJar, nil
416 default:
417 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
418 }
419 if ret == nil && err == nil {
420 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
421 }
422 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000423}
424
Jihoon Kang063ec002023-06-28 01:16:23 +0000425func (d *Droidstubs) CurrentApiTimestamp() android.Path {
426 return d.checkCurrentApiTimestamp
427}
428
Colin Cross2207f872021-03-24 12:39:08 -0700429var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
430var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
431var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000432var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000433var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700434
435func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
436 d.Javadoc.addDeps(ctx)
437
438 if len(d.properties.Merge_annotations_dirs) != 0 {
439 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
440 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
441 }
442 }
443
444 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
445 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
446 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
447 }
448 }
449
450 if len(d.properties.Api_levels_annotations_dirs) != 0 {
451 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
452 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
453 }
454 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000455
Jihoon Kang6592e872023-12-19 01:13:16 +0000456 if len(d.properties.Aconfig_declarations) != 0 {
457 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
458 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
459 }
460 }
461
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000462 if d.properties.Api_levels_module != nil {
463 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
464 }
Colin Cross2207f872021-03-24 12:39:08 -0700465}
466
Jihoon Kang3c89f042023-12-19 02:40:22 +0000467func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
468 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
469}
470
471func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
472 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700473 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000474 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000475 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000476
477 if stubsType == Everything {
478 d.apiFile = uncheckedApiFile
479 } else if stubsType == Exportable {
480 d.exportableApiFile = uncheckedApiFile
481 }
Colin Cross2207f872021-03-24 12:39:08 -0700482 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
483 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000484 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700485 }
486
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700488 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000489 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000490 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000491
492 if stubsType == Everything {
493 d.removedApiFile = uncheckedRemovedFile
494 } else if stubsType == Exportable {
495 d.exportableRemovedApiFile = uncheckedRemovedFile
496 }
Colin Cross2207f872021-03-24 12:39:08 -0700497 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
498 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000499 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700500 }
501
Colin Cross2207f872021-03-24 12:39:08 -0700502 if stubsDir.Valid() {
503 if Bool(d.properties.Create_doc_stubs) {
504 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
505 } else {
506 cmd.FlagWithArg("--stubs ", stubsDir.String())
507 if !Bool(d.properties.Output_javadoc_comments) {
508 cmd.Flag("--exclude-documentation-from-stubs")
509 }
510 }
511 }
512}
513
Jihoon Kang3c89f042023-12-19 02:40:22 +0000514func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Jihoon Kang6b93b382024-01-26 22:37:41 +0000515 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100516
Jihoon Kang6b93b382024-01-26 22:37:41 +0000517 if params.migratingNullability {
518 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
519 cmd.FlagWithInput("--migrate-nullness ", previousApi)
Colin Cross2207f872021-03-24 12:39:08 -0700520 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000521
522 if s := String(d.properties.Validate_nullability_from_list); s != "" {
523 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
524 }
525
526 if params.validatingNullability {
527 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
528 }
529
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000530 if params.extractAnnotations {
531 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
532 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000533
534 if len(d.properties.Merge_annotations_dirs) != 0 {
535 d.mergeAnnoDirFlags(ctx, cmd)
536 }
537
538 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700539}
540
541func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
542 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
543 if t, ok := m.(*ExportedDroiddocDir); ok {
544 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
545 } else {
546 ctx.PropertyErrorf("merge_annotations_dirs",
547 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
548 }
549 })
550}
551
552func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
553 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
554 if t, ok := m.(*ExportedDroiddocDir); ok {
555 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
556 } else {
557 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
558 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
559 }
560 })
561}
562
Jihoon Kang6b93b382024-01-26 22:37:41 +0000563func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000564 var apiVersions android.Path
Jihoon Kang6b93b382024-01-26 22:37:41 +0000565 stubsType := params.stubConfig.stubsType
566 apiVersionsXml := params.apiVersionsXml
567 if params.stubConfig.apiLevelsAnnotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000568 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000569 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000570 } else {
571 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
572 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000573 if stubsType == Everything {
574 apiVersions = s.everythingArtifacts.apiVersionsXml
575 } else if stubsType == Exportable {
576 apiVersions = s.exportableArtifacts.apiVersionsXml
577 } else {
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000578 // if the stubs type does not generate api-versions.xml file, default to using the
579 // everything artifacts
580 apiVersions = s.everythingArtifacts.apiVersionsXml
Jihoon Kangd9a06942024-01-26 01:49:20 +0000581 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000582 } else {
583 ctx.PropertyErrorf("api_levels_module",
584 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
585 }
586 })
Colin Cross2207f872021-03-24 12:39:08 -0700587 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000588 if apiVersions != nil {
589 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
590 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
591 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
592 }
593}
Colin Cross2207f872021-03-24 12:39:08 -0700594
Jihoon Kang3c89f042023-12-19 02:40:22 +0000595func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700596 if len(d.properties.Api_levels_annotations_dirs) == 0 {
597 ctx.PropertyErrorf("api_levels_annotations_dirs",
598 "has to be non-empty if api levels annotations was enabled!")
599 }
600
Jihoon Kang3c89f042023-12-19 02:40:22 +0000601 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700602
603 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
604
satayev783195c2021-06-23 21:49:57 +0100605 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200606 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700607 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
608 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200609 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
610
611 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
612 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700613 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200614 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
615 if extensions_dir == "" {
616 extensions_dir = t.dir.String() + "/extensions"
617 }
618 cmd.Implicit(dep)
619 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700620 if dep.Base() == filename {
621 cmd.Implicit(dep)
622 }
623 if filename != "android.jar" && dep.Base() == "android.jar" {
624 // Metalava implicitly searches these patterns:
625 // prebuilts/tools/common/api-versions/android-%/android.jar
626 // prebuilts/sdk/%/public/android.jar
627 // Add android.jar files from the api_levels_annotations_dirs directories to try
628 // to satisfy these patterns. If Metalava can't find a match for an API level
629 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700630 cmd.Implicit(dep)
631 }
632 }
satayev783195c2021-06-23 21:49:57 +0100633
634 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700635 } else {
636 ctx.PropertyErrorf("api_levels_annotations_dirs",
637 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
638 }
639 })
satayev783195c2021-06-23 21:49:57 +0100640
641 // Add all relevant --android-jar-pattern patterns for Metalava.
642 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
643 // an actual file present on disk (in the order the patterns were passed). For system APIs for
644 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000645 // for older releases. Similarly, module-lib falls back to system API.
646 var sdkDirs []string
647 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700648 case "system-server":
649 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000650 case "module-lib":
651 sdkDirs = []string{"module-lib", "system", "public"}
652 case "system":
653 sdkDirs = []string{"system", "public"}
654 case "public":
655 sdkDirs = []string{"public"}
656 default:
657 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
658 return
satayev783195c2021-06-23 21:49:57 +0100659 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000660
661 for _, sdkDir := range sdkDirs {
662 for _, dir := range dirs {
663 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
664 }
satayev783195c2021-06-23 21:49:57 +0100665 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200666
667 if d.properties.Extensions_info_file != nil {
668 if extensions_dir == "" {
669 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
670 }
671 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
672 cmd.Implicit(info_file)
673 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
674 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
675 }
Colin Cross2207f872021-03-24 12:39:08 -0700676}
677
Colin Crosse52c2ac2022-03-28 17:03:35 -0700678func metalavaUseRbe(ctx android.ModuleContext) bool {
679 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
680}
681
Colin Cross2207f872021-03-24 12:39:08 -0700682func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100683 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700684 rule.Command().Text("rm -rf").Flag(homeDir.String())
685 rule.Command().Text("mkdir -p").Flag(homeDir.String())
686
Anton Hansson556e8142021-06-04 16:20:25 +0100687 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700688 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
689
Colin Crosse52c2ac2022-03-28 17:03:35 -0700690 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700691 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700692 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000693 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
694 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700695 labels := map[string]string{"type": "tool", "name": "metalava"}
696 // TODO: metalava pool rejects these jobs
697 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
698 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000699 Labels: labels,
700 ExecStrategy: execStrategy,
701 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
702 Platform: map[string]string{remoteexec.PoolKey: pool},
703 Compare: compare,
704 NumLocalRuns: 1,
705 NumRemoteRuns: 1,
706 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700707 })
Colin Cross2207f872021-03-24 12:39:08 -0700708 }
709
Colin Cross6aa5c402021-03-24 12:28:50 -0700710 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700711 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400712 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100713 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700714 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
715 FlagWithInput("@", srcJarList)
716
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100717 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
718 // years, so it is unlikely to change any time soon.
719 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
720 combinedPaths = append(combinedPaths, classpath.Paths()...)
721 if len(combinedPaths) > 0 {
722 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700723 }
724
Liz Kammere09e20e2023-10-16 15:07:54 -0400725 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000726
Colin Cross2207f872021-03-24 12:39:08 -0700727 return cmd
728}
729
Jihoon Kang3c89f042023-12-19 02:40:22 +0000730// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
731// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
732// property is defined, apply transformations and only revert the flagged apis that are not
733// enabled via release configurations and are not specified in aconfig_declarations
734func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
735
736 if len(aconfigFlagsPaths) == 0 {
737 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
738 return
739 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000740
741 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
742 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
743
744 var filterArgs string
745 switch stubsType {
746 // No flagged apis specific flags need to be passed to metalava when generating
747 // everything stubs
748 case Everything:
749 return
750
751 case Runtime:
752 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
753
754 case Exportable:
Jihoon Kang59198152024-02-06 22:43:18 +0000755 // When the build flag RELEASE_EXPORT_RUNTIME_APIS is set to true, apis marked with
756 // the flagged apis that have read_write permissions are exposed on top of the enabled
757 // and read_only apis. This is to support local override of flag values at runtime.
758 if ctx.Config().ReleaseExportRuntimeApis() {
759 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
760 } else {
761 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
762 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000763 }
764
765 ctx.Build(pctx, android.BuildParams{
766 Rule: gatherReleasedFlaggedApisRule,
767 Inputs: aconfigFlagsPaths,
768 Output: releasedFlaggedApisFile,
769 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
770 Args: map[string]string{
771 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
772 "filter_args": filterArgs,
773 },
774 })
775
776 ctx.Build(pctx, android.BuildParams{
777 Rule: generateMetalavaRevertAnnotationsRule,
778 Input: releasedFlaggedApisFile,
779 Output: revertAnnotationsFile,
780 Description: fmt.Sprintf("%s revert annotations", stubsType),
781 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000782
783 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000784}
785
Jihoon Kang3c89f042023-12-19 02:40:22 +0000786func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
787 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700788 if BoolDefault(d.properties.High_mem, false) {
789 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
790 rule.HighMem()
791 }
792
Jihoon Kang3c89f042023-12-19 02:40:22 +0000793 if params.stubConfig.generateStubs {
794 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
795 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700796 }
797
Jihoon Kang3c89f042023-12-19 02:40:22 +0000798 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700799
Jihoon Kang3c89f042023-12-19 02:40:22 +0000800 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
801 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
802 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700803 cmd.Implicits(d.Javadoc.implicits)
804
Jihoon Kang3c89f042023-12-19 02:40:22 +0000805 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700806
Jihoon Kang3c89f042023-12-19 02:40:22 +0000807 if params.stubConfig.writeSdkValues {
808 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
809 }
810
811 annotationParams := annotationFlagsParams{
812 migratingNullability: params.stubConfig.migratingNullability,
813 validatingNullability: params.stubConfig.validatingNullability,
Jihoon Kangca2f9e82024-01-26 01:45:12 +0000814 extractAnnotations: params.stubConfig.extractAnnotations,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000815 nullabilityWarningsFile: params.nullabilityWarningsFile,
816 annotationsZip: params.annotationsZip,
817 }
818
Jihoon Kang6b93b382024-01-26 22:37:41 +0000819 if params.stubConfig.annotationsEnabled {
820 d.annotationsFlags(ctx, cmd, annotationParams)
821 }
Colin Cross2207f872021-03-24 12:39:08 -0700822 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang6b93b382024-01-26 22:37:41 +0000823 d.apiLevelsAnnotationsFlags(ctx, cmd, params)
Colin Cross2207f872021-03-24 12:39:08 -0700824
Colin Crossbc139922021-03-25 18:33:16 -0700825 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700826
Colin Cross2207f872021-03-24 12:39:08 -0700827 for _, o := range d.Javadoc.properties.Out {
828 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
829 }
830
Jihoon Kang3c89f042023-12-19 02:40:22 +0000831 return cmd
832}
Colin Cross2207f872021-03-24 12:39:08 -0700833
Jihoon Kang3c89f042023-12-19 02:40:22 +0000834// Sandbox rule for generating the everything stubs and other artifacts
835func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
836 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
837 rule := android.NewRuleBuilder(pctx, ctx)
838 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
839 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
840 SandboxInputs()
841
842 var stubsDir android.OptionalPath
843 if params.generateStubs {
844 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
845 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
846 }
847
848 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000849 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
850 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000851 }
852
Jihoon Kang6b93b382024-01-26 22:37:41 +0000853 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000854 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000855 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000856 }
Jihoon Kangee113282024-01-23 00:16:41 +0000857 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000858 }
Jihoon Kang6b93b382024-01-26 22:37:41 +0000859 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +0000860 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000861 }
862
863 commonCmdParams := stubsCommandParams{
864 srcJarDir: srcJarDir,
865 stubsDir: stubsDir,
866 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000867 metadataDir: d.everythingArtifacts.metadataDir,
868 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
869 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
870 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000871 stubConfig: params,
872 }
873
874 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
875
876 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
877
878 if params.generateStubs {
879 rule.Command().
880 BuiltTool("soong_zip").
881 Flag("-write_if_changed").
882 Flag("-jar").
883 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
884 FlagWithArg("-C ", stubsDir.String()).
885 FlagWithArg("-D ", stubsDir.String())
886 }
887
888 if params.writeSdkValues {
889 rule.Command().
890 BuiltTool("soong_zip").
891 Flag("-write_if_changed").
892 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000893 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
894 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
895 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000896 }
897
898 // TODO: We don't really need two separate API files, but this is a reminiscence of how
899 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
900 if params.doApiLint {
901 rule.Command().Text("touch").Output(d.apiLintTimestamp)
902 }
903 if params.doCheckReleased {
904 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
905 }
906
907 // TODO(b/183630617): rewrapper doesn't support restat rules
908 if !metalavaUseRbe(ctx) {
909 rule.Restat()
910 }
911
912 zipSyncCleanupCmd(rule, srcJarDir)
913
914 rule.Build("metalava", "metalava merged")
915}
916
917// Sandbox rule for generating the everything artifacts that are not run by
918// default but only run based on the module configurations
919func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700920
921 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000922 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700923 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
924 if newSince.Valid() {
925 cmd.FlagWithInput("--api-lint ", newSince.Path())
926 } else {
927 cmd.Flag("--api-lint")
928 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000929 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700930 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
931
Colin Cross0d532412021-03-25 09:38:45 -0700932 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700933 if d.Name() != "android.car-system-stubs-docs" &&
934 d.Name() != "android.car-stubs-docs" {
935 cmd.Flag("--lints-as-errors")
936 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
937 }
938
939 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000940 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
941 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700942
943 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700944 //
945 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
946 // message and metalava's one?
947 msg := `$'` + // Enclose with $' ... '
948 `************************************************************\n` +
949 `Your API changes are triggering API Lint warnings or errors.\n` +
950 `To make these errors go away, fix the code according to the\n` +
951 `error and/or warning messages above.\n` +
952 `\n` +
953 `If it is not possible to do so, there are workarounds:\n` +
954 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000955 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
956 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700957
958 if baselineFile.Valid() {
959 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
960 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
961
962 msg += fmt.Sprintf(``+
963 `2. You can update the baseline by executing the following\n`+
964 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700965 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
966 ` "%s" \\\n`+
967 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700968 ` To submit the revised baseline.txt to the main Android\n`+
969 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
970 } else {
971 msg += fmt.Sprintf(``+
972 `2. You can add a baseline file of existing lint failures\n`+
973 ` to the build rule of %s.\n`, d.Name())
974 }
975 // Note the message ends with a ' (single quote), to close the $' ... ' .
976 msg += `************************************************************\n'`
977
978 cmd.FlagWithArg("--error-message:api-lint ", msg)
979 }
980
981 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000982 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700983 if len(d.Javadoc.properties.Out) > 0 {
984 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
985 }
986
987 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
988 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
989 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000990 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700991
Jihoon Kang3c89f042023-12-19 02:40:22 +0000992 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700993
994 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
995 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
996
997 if baselineFile.Valid() {
998 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
999 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
1000 }
1001
1002 // Note this string includes quote ($' ... '), which decodes the "\n"s.
1003 msg := `$'\n******************************\n` +
1004 `You have tried to change the API from what has been previously released in\n` +
1005 `an SDK. Please fix the errors listed above.\n` +
1006 `******************************\n'`
1007
1008 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
1009 }
1010
Paul Duffin10a23c22023-08-11 22:47:31 +01001011 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1012 // Pass the current API file into metalava so it can use it as the basis for determining how to
1013 // generate the output signature files (both api and removed).
1014 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1015 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
1016 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001017}
Paul Duffin10a23c22023-08-11 22:47:31 +01001018
Jihoon Kang3c89f042023-12-19 02:40:22 +00001019// Sandbox rule for generating exportable stubs and other artifacts
1020func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1021 optionalCmdParams := stubsCommandParams{
1022 stubConfig: params,
1023 }
1024
Jihoon Kang246690a2024-02-01 21:55:01 +00001025 if params.generateStubs {
1026 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1027 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1028 }
1029
Jihoon Kang3c89f042023-12-19 02:40:22 +00001030 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001031 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1032 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1033 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1034 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001035 }
1036
Jihoon Kang6b93b382024-01-26 22:37:41 +00001037 if params.annotationsEnabled {
Jihoon Kang3c89f042023-12-19 02:40:22 +00001038 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001039 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1040 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001041 }
Jihoon Kangee113282024-01-23 00:16:41 +00001042 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1043 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001044 }
Jihoon Kang6b93b382024-01-26 22:37:41 +00001045 if params.apiLevelsAnnotationsEnabled {
Jihoon Kangee113282024-01-23 00:16:41 +00001046 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1047 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001048 }
1049
1050 if params.checkApi || String(d.properties.Api_filename) != "" {
1051 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1052 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1053 }
1054
1055 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1056 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1057 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1058 }
1059
1060 d.optionalStubCmd(ctx, optionalCmdParams)
1061}
1062
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001063// Sandbox rule for generating runtime stubs
1064func (d *Droidstubs) runtimeStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1065
1066 // We are only interested in generating the stubs srcjar,
1067 // not other artifacts for the runtime stubs
1068 params.checkApi = false
1069 params.writeSdkValues = false
1070 params.validatingNullability = false
1071 params.extractAnnotations = false
1072 params.apiLevelsAnnotationsEnabled = false
1073
1074 optionalCmdParams := stubsCommandParams{
1075 stubConfig: params,
1076 }
1077
1078 d.Javadoc.runtimeStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1079 optionalCmdParams.stubsSrcJar = d.Javadoc.runtimeStubsSrcJar
1080
1081 // If aconfig_declarations property is not defined, all flagged apis symbols are stripped
1082 // as no aconfig flags are enabled. In such case, the runtime stubs are identical to the
1083 // exportable stubs, thus no additional metalava invocation is needed.
1084 if len(d.properties.Aconfig_declarations) == 0 {
1085 rule := android.NewRuleBuilder(pctx, ctx)
1086 rule.Command().
1087 Text("cp").Flag("-f").
1088 Input(d.exportableStubsSrcJar).Output(d.runtimeStubsSrcJar)
1089 rule.Build(fmt.Sprintf("metalava_%s", params.stubsType.String()), "metalava merged")
1090 } else {
1091 d.optionalStubCmd(ctx, optionalCmdParams)
1092 }
1093}
1094
Jihoon Kang3c89f042023-12-19 02:40:22 +00001095func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1096
1097 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1098 rule := android.NewRuleBuilder(pctx, ctx)
1099 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1100 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1101 SandboxInputs()
1102
1103 if params.stubConfig.generateStubs {
1104 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1105 }
1106
1107 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1108
1109 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1110
1111 if params.stubConfig.doApiLint {
1112 // Pass the lint baseline file as an input to resolve the lint errors.
1113 // The exportable stubs generation does not update the lint baseline file.
1114 // Lint baseline file update is handled by the everything stubs
1115 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1116 if baselineFile.Valid() {
1117 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1118 }
1119 }
1120
1121 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001122 rule.Command().
1123 BuiltTool("soong_zip").
1124 Flag("-write_if_changed").
1125 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001126 FlagWithOutput("-o ", params.stubsSrcJar).
1127 FlagWithArg("-C ", params.stubsDir.String()).
1128 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001129 }
1130
Jihoon Kang3c89f042023-12-19 02:40:22 +00001131 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001132 rule.Command().
1133 BuiltTool("soong_zip").
1134 Flag("-write_if_changed").
1135 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001136 FlagWithOutput("-o ", params.metadataZip).
1137 FlagWithArg("-C ", params.metadataDir.String()).
1138 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001139 }
1140
Colin Cross6aa5c402021-03-24 12:28:50 -07001141 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001142 if !metalavaUseRbe(ctx) {
1143 rule.Restat()
1144 }
Colin Cross2207f872021-03-24 12:39:08 -07001145
Jihoon Kang3c89f042023-12-19 02:40:22 +00001146 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001147
Jihoon Kang3c89f042023-12-19 02:40:22 +00001148 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1149}
1150
1151func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1152 deps := d.Javadoc.collectDeps(ctx)
1153
1154 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1155 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1156
1157 // Add options for the other optional tasks: API-lint and check-released.
1158 // We generate separate timestamp files for them.
1159 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1160 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1161
1162 writeSdkValues := Bool(d.properties.Write_sdk_values)
1163
1164 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1165
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001166 extractAnnotations := annotationsEnabled
1167
Jihoon Kang3c89f042023-12-19 02:40:22 +00001168 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1169 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1170 String(d.properties.Validate_nullability_from_list) != "")
1171
1172 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1173 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1174
Jihoon Kang6b93b382024-01-26 22:37:41 +00001175 apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
1176
Jihoon Kang3c89f042023-12-19 02:40:22 +00001177 stubCmdParams := stubsCommandConfigParams{
Jihoon Kang6b93b382024-01-26 22:37:41 +00001178 javaVersion: javaVersion,
1179 deps: deps,
1180 checkApi: checkApi,
1181 generateStubs: generateStubs,
1182 doApiLint: doApiLint,
1183 doCheckReleased: doCheckReleased,
1184 writeSdkValues: writeSdkValues,
1185 migratingNullability: migratingNullability,
1186 validatingNullability: validatingNullability,
1187 annotationsEnabled: annotationsEnabled,
1188 apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001189 extractAnnotations: extractAnnotations,
Jihoon Kang3c89f042023-12-19 02:40:22 +00001190 }
1191 stubCmdParams.stubsType = Everything
1192 // Create default (i.e. "everything" stubs) rule for metalava
1193 d.everythingStubCmd(ctx, stubCmdParams)
1194
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001195 // The module generates "exportable" stubs regardless of whether
Jihoon Kang3c89f042023-12-19 02:40:22 +00001196 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1197 // strips all flagged apis to generate the "exportable" stubs
1198 stubCmdParams.stubsType = Exportable
1199 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001200
Jihoon Kangca2f9e82024-01-26 01:45:12 +00001201 // "runtime" stubs do not generate any other artifacts than the stubs.
1202 // Therefore, metalava does not have to run for "runtime" configuration
1203 // when the module does not generate stubs.
1204 if stubCmdParams.generateStubs {
1205 stubCmdParams.stubsType = Runtime
1206 d.runtimeStubCmd(ctx, stubCmdParams)
1207 }
1208
Paul Duffine7a86642022-08-16 15:43:20 +00001209 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1210
1211 if len(d.Javadoc.properties.Out) > 0 {
1212 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1213 }
1214
1215 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1216 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1217 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1218
1219 if baselineFile.Valid() {
1220 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1221 }
1222
Jihoon Kang3c89f042023-12-19 02:40:22 +00001223 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001224
1225 rule := android.NewRuleBuilder(pctx, ctx)
1226
1227 // Diff command line.
1228 // -F matches the closest "opening" line, such as "package android {"
1229 // and " public class Intent {".
1230 diff := `diff -u -F '{ *$'`
1231
1232 rule.Command().Text("( true")
1233 rule.Command().
1234 Text(diff).
1235 Input(apiFile).Input(d.apiFile)
1236
1237 rule.Command().
1238 Text(diff).
1239 Input(removedApiFile).Input(d.removedApiFile)
1240
1241 msg := fmt.Sprintf(`\n******************************\n`+
1242 `You have tried to change the API from what has been previously approved.\n\n`+
1243 `To make these errors go away, you have two choices:\n`+
1244 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1245 ` to the new methods, etc. shown in the above diff.\n\n`+
1246 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1247 ` m %s-update-current-api\n\n`+
1248 ` To submit the revised current.txt to the main Android repository,\n`+
1249 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001250 `If your build failed due to stub validation, you can resolve the errors with\n`+
1251 `either of the two choices above and try re-building the target.\n`+
1252 `If the mismatch between the stubs and the current.txt is intended,\n`+
1253 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001254 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1255 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001256 `******************************\n`, ctx.ModuleName())
1257
1258 rule.Command().
1259 Text("touch").Output(d.checkCurrentApiTimestamp).
1260 Text(") || (").
1261 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1262 Text("; exit 38").
1263 Text(")")
1264
1265 rule.Build("metalavaCurrentApiCheck", "check current API")
1266
Jihoon Kang3c89f042023-12-19 02:40:22 +00001267 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001268
1269 // update API rule
1270 rule = android.NewRuleBuilder(pctx, ctx)
1271
1272 rule.Command().Text("( true")
1273
1274 rule.Command().
1275 Text("cp").Flag("-f").
1276 Input(d.apiFile).Flag(apiFile.String())
1277
1278 rule.Command().
1279 Text("cp").Flag("-f").
1280 Input(d.removedApiFile).Flag(removedApiFile.String())
1281
1282 msg = "failed to update public API"
1283
1284 rule.Command().
1285 Text("touch").Output(d.updateCurrentApiTimestamp).
1286 Text(") || (").
1287 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1288 Text("; exit 38").
1289 Text(")")
1290
1291 rule.Build("metalavaCurrentApiUpdate", "update current API")
1292 }
1293
Colin Cross2207f872021-03-24 12:39:08 -07001294 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001295 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001296 ctx.PropertyErrorf("check_nullability_warnings",
1297 "Cannot specify check_nullability_warnings unless validating nullability")
1298 }
1299
1300 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1301
Jihoon Kang3c89f042023-12-19 02:40:22 +00001302 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001303
1304 msg := fmt.Sprintf(`\n******************************\n`+
1305 `The warnings encountered during nullability annotation validation did\n`+
1306 `not match the checked in file of expected warnings. The diffs are shown\n`+
1307 `above. You have two options:\n`+
1308 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1309 ` 2. Update the file of expected warnings by running:\n`+
1310 ` cp %s %s\n`+
1311 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001312 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001313
1314 rule := android.NewRuleBuilder(pctx, ctx)
1315
1316 rule.Command().
1317 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001318 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001319 Text("&&").
1320 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1321 Text(") || (").
1322 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1323 Text("; exit 38").
1324 Text(")")
1325
1326 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1327 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001328 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001329}
1330
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001331func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1332 api_file := d.properties.Check_api.Current.Api_file
1333 api_surface := d.properties.Api_surface
1334
1335 props := struct {
1336 Name *string
1337 Api_surface *string
1338 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001339 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001340 }{}
1341
1342 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1343 props.Api_surface = api_surface
1344 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001345 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001346
1347 ctx.CreateModule(ApiContributionFactory, &props)
1348}
1349
Spandan Das0b555e32022-11-28 18:48:51 +00001350// TODO (b/262014796): Export the API contributions of CorePlatformApi
1351// A map to populate the api surface of a droidstub from a substring appearing in its name
1352// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1353// use a strict naming convention
1354var (
1355 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1356 //public is commented out since the core libraries use public in their java_sdk_library names
1357 "intracore": android.SdkIntraCore,
1358 "intra.core": android.SdkIntraCore,
1359 "system_server": android.SdkSystemServer,
1360 "system-server": android.SdkSystemServer,
1361 "system": android.SdkSystem,
1362 "module_lib": android.SdkModule,
1363 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001364 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001365 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001366 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001367 }
1368)
1369
Colin Cross2207f872021-03-24 12:39:08 -07001370func StubsDefaultsFactory() android.Module {
1371 module := &DocDefaults{}
1372
1373 module.AddProperties(
1374 &JavadocProperties{},
1375 &DroidstubsProperties{},
1376 )
1377
1378 android.InitDefaultsModule(module)
1379
1380 return module
1381}
1382
1383var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1384
1385type PrebuiltStubsSourcesProperties struct {
1386 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001387
1388 // Name of the source soong module that gets shadowed by this prebuilt
1389 // If unspecified, follows the naming convention that the source module of
1390 // the prebuilt is Name() without "prebuilt_" prefix
1391 Source_module_name *string
1392
1393 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1394 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1395 // (without any prebuilt_ prefix)
1396 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1397}
1398
1399func (j *PrebuiltStubsSources) BaseModuleName() string {
1400 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1401}
1402
1403func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1404 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001405}
1406
1407type PrebuiltStubsSources struct {
1408 android.ModuleBase
1409 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001410 embeddableInModuleAndImport
1411
Colin Cross2207f872021-03-24 12:39:08 -07001412 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001413
1414 properties PrebuiltStubsSourcesProperties
1415
kgui67007242022-01-25 13:50:25 +08001416 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001417}
1418
1419func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1420 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001421 // prebuilt droidstubs does not output "exportable" stubs.
1422 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1423 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001424 return android.Paths{p.stubsSrcJar}, nil
1425 default:
1426 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1427 }
1428}
1429
Jihoon Kangee113282024-01-23 00:16:41 +00001430func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1431 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001432}
1433
1434func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001435 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001436 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 -07001437 return
1438 }
1439
Anton Hansson86758ac2021-11-03 14:44:12 +00001440 src := p.properties.Srcs[0]
1441 if filepath.Ext(src) == ".srcjar" {
1442 // This is a srcjar. We can use it directly.
1443 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1444 } else {
1445 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001446
Anton Hansson86758ac2021-11-03 14:44:12 +00001447 // This is a directory. Glob the contents just in case the directory does not exist.
1448 srcGlob := src + "/**/*"
1449 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001450
Anton Hansson86758ac2021-11-03 14:44:12 +00001451 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1452 // the path components are invalid it won't in this case because no components
1453 // are specified and the module directory must exist in order to get this far.
1454 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001455
Anton Hansson86758ac2021-11-03 14:44:12 +00001456 rule := android.NewRuleBuilder(pctx, ctx)
1457 rule.Command().
1458 BuiltTool("soong_zip").
1459 Flag("-write_if_changed").
1460 Flag("-jar").
1461 FlagWithOutput("-o ", outPath).
1462 FlagWithArg("-C ", srcDir.String()).
1463 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1464 rule.Restat()
1465 rule.Build("zip src", "Create srcjar from prebuilt source")
1466 p.stubsSrcJar = outPath
1467 }
Colin Cross2207f872021-03-24 12:39:08 -07001468}
1469
1470func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1471 return &p.prebuilt
1472}
1473
1474func (p *PrebuiltStubsSources) Name() string {
1475 return p.prebuilt.Name(p.ModuleBase.Name())
1476}
1477
1478// prebuilt_stubs_sources imports a set of java source files as if they were
1479// generated by droidstubs.
1480//
1481// By default, a prebuilt_stubs_sources has a single variant that expects a
1482// set of `.java` files generated by droidstubs.
1483//
1484// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1485// for host modules.
1486//
1487// Intended only for use by sdk snapshots.
1488func PrebuiltStubsSourcesFactory() android.Module {
1489 module := &PrebuiltStubsSources{}
1490
1491 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001492 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001493
1494 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001495 InitDroiddocModule(module, android.HostAndDeviceSupported)
1496 return module
1497}