blob: 56ae427ac4b5ece8fbb0b1e8a30b8365ae5b5c37 [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 {
232 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}
243
Colin Cross2207f872021-03-24 12:39:08 -0700244// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
245// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
246// a droiddoc module to generate documentation.
247func DroidstubsFactory() android.Module {
248 module := &Droidstubs{}
249
250 module.AddProperties(&module.properties,
251 &module.Javadoc.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +0000252 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -0700253
254 InitDroiddocModule(module, android.HostAndDeviceSupported)
Jihoon Kang3198f3c2023-01-26 08:08:52 +0000255
256 module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
257 module.createApiContribution(ctx)
258 })
Colin Cross2207f872021-03-24 12:39:08 -0700259 return module
260}
261
262// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
263// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
264// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
265// module when symbols needed by the source files are provided by java_library_host modules.
266func DroidstubsHostFactory() android.Module {
267 module := &Droidstubs{}
268
269 module.AddProperties(&module.properties,
270 &module.Javadoc.properties)
271
272 InitDroiddocModule(module, android.HostSupported)
273 return module
274}
275
Jihoon Kang78f89142023-12-27 01:40:29 +0000276func getStubsTypeAndTag(tag string) (StubsType, string, error) {
277 if len(tag) == 0 {
278 return Everything, "", nil
279 }
280 if tag[0] != '.' {
281 return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
282 }
283
284 stubsType := Everything
285 // Check if the tag has a stubs type prefix (e.g. ".exportable")
286 for st := Everything; st <= Exportable; st++ {
287 if strings.HasPrefix(tag, "."+st.String()) {
288 stubsType = st
289 }
290 }
291
292 return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
293}
294
295// Droidstubs' tag supports specifying with the stubs type.
296// While supporting the pre-existing tags, it also supports tags with
297// the stubs type prefix. Some examples are shown below:
298// {.annotations.zip} - pre-existing behavior. Returns the path to the
299// annotation zip.
300// {.exportable} - Returns the path to the exportable stubs src jar.
301// {.exportable.annotations.zip} - Returns the path to the exportable
302// annotations zip file.
303// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
304// xml file. For unsupported combinations, the default everything output file
305// is returned.
Colin Cross2207f872021-03-24 12:39:08 -0700306func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000307 stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
308 if err != nil {
309 return nil, err
310 }
311 switch prefixRemovedTag {
Colin Cross2207f872021-03-24 12:39:08 -0700312 case "":
Jihoon Kangee113282024-01-23 00:16:41 +0000313 stubsSrcJar, err := d.StubsSrcJar(stubsType)
314 return android.Paths{stubsSrcJar}, err
Colin Cross2207f872021-03-24 12:39:08 -0700315 case ".docs.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000316 docZip, err := d.DocZip(stubsType)
317 return android.Paths{docZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700318 case ".api.txt", android.DefaultDistTag:
319 // This is the default dist path for dist properties that have no tag property.
Jihoon Kangee113282024-01-23 00:16:41 +0000320 apiFilePath, err := d.ApiFilePath(stubsType)
321 return android.Paths{apiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700322 case ".removed-api.txt":
Jihoon Kangee113282024-01-23 00:16:41 +0000323 removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
324 return android.Paths{removedApiFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700325 case ".annotations.zip":
Jihoon Kangee113282024-01-23 00:16:41 +0000326 annotationsZip, err := d.AnnotationsZip(stubsType)
327 return android.Paths{annotationsZip}, err
Colin Cross2207f872021-03-24 12:39:08 -0700328 case ".api_versions.xml":
Jihoon Kangee113282024-01-23 00:16:41 +0000329 apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
330 return android.Paths{apiVersionsXmlFilePath}, err
Colin Cross2207f872021-03-24 12:39:08 -0700331 default:
332 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
333 }
334}
335
Jihoon Kang246690a2024-02-01 21:55:01 +0000336func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000337 switch stubsType {
338 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000339 ret, err = d.everythingArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000340 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000341 ret, err = d.exportableArtifacts.annotationsZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000342 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000343 ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000344 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000345 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000346}
347
Jihoon Kang246690a2024-02-01 21:55:01 +0000348func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000349 switch stubsType {
350 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000351 ret, err = d.apiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000352 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000353 ret, err = d.exportableApiFile, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000354 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000355 ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000356 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000357 if ret == nil && err == nil {
358 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
359 }
360 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000361}
362
Jihoon Kang246690a2024-02-01 21:55:01 +0000363func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000364 switch stubsType {
365 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000366 ret, err = d.everythingArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000367 case Exportable:
Jihoon Kang246690a2024-02-01 21:55:01 +0000368 ret, err = d.exportableArtifacts.apiVersionsXml, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000369 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000370 ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000371 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000372 if ret == nil && err == nil {
373 err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
374 }
375 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000376}
377
Jihoon Kang246690a2024-02-01 21:55:01 +0000378func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
Jihoon Kang78f89142023-12-27 01:40:29 +0000379 switch stubsType {
380 case Everything:
Jihoon Kang246690a2024-02-01 21:55:01 +0000381 ret, err = d.docZip, nil
Jihoon Kang78f89142023-12-27 01:40:29 +0000382 default:
Jihoon Kang246690a2024-02-01 21:55:01 +0000383 ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
Jihoon Kang78f89142023-12-27 01:40:29 +0000384 }
Jihoon Kang246690a2024-02-01 21:55:01 +0000385 if ret == nil && err == nil {
386 err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
387 }
388 return ret, err
389}
390
391func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
392 switch stubsType {
393 case Everything:
394 ret, err = d.removedApiFile, nil
395 case Exportable:
396 ret, err = d.exportableRemovedApiFile, nil
397 default:
398 ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
399 }
400 if ret == nil && err == nil {
401 err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
402 }
403 return ret, err
404}
405
406func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
407 switch stubsType {
408 case Everything:
409 ret, err = d.stubsSrcJar, nil
410 case Exportable:
411 ret, err = d.exportableStubsSrcJar, nil
412 default:
413 ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
414 }
415 if ret == nil && err == nil {
416 err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
417 }
418 return ret, err
Jihoon Kang78f89142023-12-27 01:40:29 +0000419}
420
Jihoon Kang063ec002023-06-28 01:16:23 +0000421func (d *Droidstubs) CurrentApiTimestamp() android.Path {
422 return d.checkCurrentApiTimestamp
423}
424
Colin Cross2207f872021-03-24 12:39:08 -0700425var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
426var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
427var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000428var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
Jihoon Kang063ec002023-06-28 01:16:23 +0000429var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
Colin Cross2207f872021-03-24 12:39:08 -0700430
431func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
432 d.Javadoc.addDeps(ctx)
433
434 if len(d.properties.Merge_annotations_dirs) != 0 {
435 for _, mergeAnnotationsDir := range d.properties.Merge_annotations_dirs {
436 ctx.AddDependency(ctx.Module(), metalavaMergeAnnotationsDirTag, mergeAnnotationsDir)
437 }
438 }
439
440 if len(d.properties.Merge_inclusion_annotations_dirs) != 0 {
441 for _, mergeInclusionAnnotationsDir := range d.properties.Merge_inclusion_annotations_dirs {
442 ctx.AddDependency(ctx.Module(), metalavaMergeInclusionAnnotationsDirTag, mergeInclusionAnnotationsDir)
443 }
444 }
445
446 if len(d.properties.Api_levels_annotations_dirs) != 0 {
447 for _, apiLevelsAnnotationsDir := range d.properties.Api_levels_annotations_dirs {
448 ctx.AddDependency(ctx.Module(), metalavaAPILevelsAnnotationsDirTag, apiLevelsAnnotationsDir)
449 }
450 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000451
Jihoon Kang6592e872023-12-19 01:13:16 +0000452 if len(d.properties.Aconfig_declarations) != 0 {
453 for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
454 ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
455 }
456 }
457
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000458 if d.properties.Api_levels_module != nil {
459 ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
460 }
Colin Cross2207f872021-03-24 12:39:08 -0700461}
462
Jihoon Kang3c89f042023-12-19 02:40:22 +0000463func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
464 cmd.FlagWithArg("--sdk-values ", metadataDir.String())
465}
466
467func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
468 if checkApi || String(d.properties.Api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700469 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000470 uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000471 cmd.FlagWithOutput("--api ", uncheckedApiFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000472
473 if stubsType == Everything {
474 d.apiFile = uncheckedApiFile
475 } else if stubsType == Exportable {
476 d.exportableApiFile = uncheckedApiFile
477 }
Colin Cross2207f872021-03-24 12:39:08 -0700478 } else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
479 // If check api is disabled then make the source file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000480 d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700481 }
482
Jihoon Kang3c89f042023-12-19 02:40:22 +0000483 if checkApi || String(d.properties.Removed_api_filename) != "" {
Colin Cross2207f872021-03-24 12:39:08 -0700484 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000485 uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
Paul Duffinc71d2b72022-08-16 15:24:01 +0000486 cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000487
488 if stubsType == Everything {
489 d.removedApiFile = uncheckedRemovedFile
490 } else if stubsType == Exportable {
491 d.exportableRemovedApiFile = uncheckedRemovedFile
492 }
Colin Cross2207f872021-03-24 12:39:08 -0700493 } else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
494 // If check api is disabled then make the source removed api file available for export.
Paul Duffinc71d2b72022-08-16 15:24:01 +0000495 d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
Colin Cross2207f872021-03-24 12:39:08 -0700496 }
497
Colin Cross2207f872021-03-24 12:39:08 -0700498 if stubsDir.Valid() {
499 if Bool(d.properties.Create_doc_stubs) {
500 cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
501 } else {
502 cmd.FlagWithArg("--stubs ", stubsDir.String())
503 if !Bool(d.properties.Output_javadoc_comments) {
504 cmd.Flag("--exclude-documentation-from-stubs")
505 }
506 }
507 }
508}
509
Jihoon Kang3c89f042023-12-19 02:40:22 +0000510func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
Colin Cross2207f872021-03-24 12:39:08 -0700511 if Bool(d.properties.Annotations_enabled) {
Liz Kammere09e20e2023-10-16 15:07:54 -0400512 cmd.Flag(config.MetalavaAnnotationsFlags)
Andrei Onea4985e512021-04-29 16:29:34 +0100513
Jihoon Kang3c89f042023-12-19 02:40:22 +0000514 if params.migratingNullability {
Colin Cross2207f872021-03-24 12:39:08 -0700515 previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
516 cmd.FlagWithInput("--migrate-nullness ", previousApi)
517 }
518
519 if s := String(d.properties.Validate_nullability_from_list); s != "" {
520 cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
521 }
522
Jihoon Kang3c89f042023-12-19 02:40:22 +0000523 if params.validatingNullability {
524 cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
Colin Cross2207f872021-03-24 12:39:08 -0700525 }
526
Jihoon Kang3c89f042023-12-19 02:40:22 +0000527 cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
Colin Cross2207f872021-03-24 12:39:08 -0700528
529 if len(d.properties.Merge_annotations_dirs) != 0 {
530 d.mergeAnnoDirFlags(ctx, cmd)
531 }
532
Liz Kammere09e20e2023-10-16 15:07:54 -0400533 cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
Colin Cross2207f872021-03-24 12:39:08 -0700534 }
535}
536
537func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
538 ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) {
539 if t, ok := m.(*ExportedDroiddocDir); ok {
540 cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps)
541 } else {
542 ctx.PropertyErrorf("merge_annotations_dirs",
543 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
544 }
545 })
546}
547
548func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
549 ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) {
550 if t, ok := m.(*ExportedDroiddocDir); ok {
551 cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps)
552 } else {
553 ctx.PropertyErrorf("merge_inclusion_annotations_dirs",
554 "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m))
555 }
556 })
557}
558
Jihoon Kang3c89f042023-12-19 02:40:22 +0000559func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000560 var apiVersions android.Path
561 if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kang3c89f042023-12-19 02:40:22 +0000562 d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
Jihoon Kangd9a06942024-01-26 01:49:20 +0000563 apiVersions = apiVersionsXml
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000564 } else {
565 ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
566 if s, ok := m.(*Droidstubs); ok {
Jihoon Kangd9a06942024-01-26 01:49:20 +0000567 if stubsType == Everything {
568 apiVersions = s.everythingArtifacts.apiVersionsXml
569 } else if stubsType == Exportable {
570 apiVersions = s.exportableArtifacts.apiVersionsXml
571 } else {
572 ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
573 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000574 } else {
575 ctx.PropertyErrorf("api_levels_module",
576 "module %q is not a droidstubs module", ctx.OtherModuleName(m))
577 }
578 })
Colin Cross2207f872021-03-24 12:39:08 -0700579 }
Anton Hanssonc04a16e2022-05-09 09:30:26 +0000580 if apiVersions != nil {
581 cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
582 cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
583 cmd.FlagWithInput("--apply-api-levels ", apiVersions)
584 }
585}
Colin Cross2207f872021-03-24 12:39:08 -0700586
Jihoon Kang3c89f042023-12-19 02:40:22 +0000587func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
Colin Cross2207f872021-03-24 12:39:08 -0700588 if len(d.properties.Api_levels_annotations_dirs) == 0 {
589 ctx.PropertyErrorf("api_levels_annotations_dirs",
590 "has to be non-empty if api levels annotations was enabled!")
591 }
592
Jihoon Kang3c89f042023-12-19 02:40:22 +0000593 cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700594
595 filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
596
satayev783195c2021-06-23 21:49:57 +0100597 var dirs []string
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200598 var extensions_dir string
Colin Cross2207f872021-03-24 12:39:08 -0700599 ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) {
600 if t, ok := m.(*ExportedDroiddocDir); ok {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200601 extRegex := regexp.MustCompile(t.dir.String() + `/extensions/[0-9]+/public/.*\.jar`)
602
603 // Grab the first extensions_dir and we find while scanning ExportedDroiddocDir.deps;
604 // ideally this should be read from prebuiltApis.properties.Extensions_*
Colin Cross2207f872021-03-24 12:39:08 -0700605 for _, dep := range t.deps {
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200606 if extRegex.MatchString(dep.String()) && d.properties.Extensions_info_file != nil {
607 if extensions_dir == "" {
608 extensions_dir = t.dir.String() + "/extensions"
609 }
610 cmd.Implicit(dep)
611 }
Colin Cross5f6ffc72021-03-29 21:54:45 -0700612 if dep.Base() == filename {
613 cmd.Implicit(dep)
614 }
615 if filename != "android.jar" && dep.Base() == "android.jar" {
616 // Metalava implicitly searches these patterns:
617 // prebuilts/tools/common/api-versions/android-%/android.jar
618 // prebuilts/sdk/%/public/android.jar
619 // Add android.jar files from the api_levels_annotations_dirs directories to try
620 // to satisfy these patterns. If Metalava can't find a match for an API level
621 // between 1 and 28 in at least one pattern it will fail.
Colin Cross2207f872021-03-24 12:39:08 -0700622 cmd.Implicit(dep)
623 }
624 }
satayev783195c2021-06-23 21:49:57 +0100625
626 dirs = append(dirs, t.dir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700627 } else {
628 ctx.PropertyErrorf("api_levels_annotations_dirs",
629 "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m))
630 }
631 })
satayev783195c2021-06-23 21:49:57 +0100632
633 // Add all relevant --android-jar-pattern patterns for Metalava.
634 // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines
635 // an actual file present on disk (in the order the patterns were passed). For system APIs for
636 // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs
Pedro Loureirocc203502021-10-04 17:24:00 +0000637 // for older releases. Similarly, module-lib falls back to system API.
638 var sdkDirs []string
639 switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") {
Cole Faust051fa912022-10-05 12:45:42 -0700640 case "system-server":
641 sdkDirs = []string{"system-server", "module-lib", "system", "public"}
Pedro Loureirocc203502021-10-04 17:24:00 +0000642 case "module-lib":
643 sdkDirs = []string{"module-lib", "system", "public"}
644 case "system":
645 sdkDirs = []string{"system", "public"}
646 case "public":
647 sdkDirs = []string{"public"}
648 default:
649 ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes)
650 return
satayev783195c2021-06-23 21:49:57 +0100651 }
Pedro Loureirocc203502021-10-04 17:24:00 +0000652
653 for _, sdkDir := range sdkDirs {
654 for _, dir := range dirs {
655 cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename))
656 }
satayev783195c2021-06-23 21:49:57 +0100657 }
MÃ¥rten Kongstad802ae0f2022-07-27 13:47:32 +0200658
659 if d.properties.Extensions_info_file != nil {
660 if extensions_dir == "" {
661 ctx.ModuleErrorf("extensions_info_file set, but no SDK extension dirs found")
662 }
663 info_file := android.PathForModuleSrc(ctx, *d.properties.Extensions_info_file)
664 cmd.Implicit(info_file)
665 cmd.FlagWithArg("--sdk-extensions-root ", extensions_dir)
666 cmd.FlagWithArg("--sdk-extensions-info ", info_file.String())
667 }
Colin Cross2207f872021-03-24 12:39:08 -0700668}
669
Colin Crosse52c2ac2022-03-28 17:03:35 -0700670func metalavaUseRbe(ctx android.ModuleContext) bool {
671 return ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA")
672}
673
Colin Cross2207f872021-03-24 12:39:08 -0700674func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
Anton Hansson556e8142021-06-04 16:20:25 +0100675 srcJarList android.Path, bootclasspath, classpath classpath, homeDir android.WritablePath) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700676 rule.Command().Text("rm -rf").Flag(homeDir.String())
677 rule.Command().Text("mkdir -p").Flag(homeDir.String())
678
Anton Hansson556e8142021-06-04 16:20:25 +0100679 cmd := rule.Command()
Colin Cross2207f872021-03-24 12:39:08 -0700680 cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
681
Colin Crosse52c2ac2022-03-28 17:03:35 -0700682 if metalavaUseRbe(ctx) {
Colin Cross2207f872021-03-24 12:39:08 -0700683 rule.Remoteable(android.RemoteRuleSupports{RBE: true})
Colin Cross8095c292021-03-30 16:40:48 -0700684 execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000685 compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
686 remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
Colin Cross8095c292021-03-30 16:40:48 -0700687 labels := map[string]string{"type": "tool", "name": "metalava"}
688 // TODO: metalava pool rejects these jobs
689 pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
690 rule.Rewrapper(&remoteexec.REParams{
Anas Sulaiman9d7a36d2023-11-21 23:00:07 +0000691 Labels: labels,
692 ExecStrategy: execStrategy,
693 ToolchainInputs: []string{config.JavaCmd(ctx).String()},
694 Platform: map[string]string{remoteexec.PoolKey: pool},
695 Compare: compare,
696 NumLocalRuns: 1,
697 NumRemoteRuns: 1,
698 NoRemoteUpdateCache: !remoteUpdateCache,
Colin Cross8095c292021-03-30 16:40:48 -0700699 })
Colin Cross2207f872021-03-24 12:39:08 -0700700 }
701
Colin Cross6aa5c402021-03-24 12:28:50 -0700702 cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Colin Cross2207f872021-03-24 12:39:08 -0700703 Flag(config.JavacVmFlags).
Liz Kammere09e20e2023-10-16 15:07:54 -0400704 Flag(config.MetalavaAddOpens).
Paul Duffin808211e2023-08-09 12:36:08 +0100705 FlagWithArg("--java-source ", javaVersion.String()).
Colin Cross2207f872021-03-24 12:39:08 -0700706 FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
707 FlagWithInput("@", srcJarList)
708
Paul Duffinf8aaaa12023-08-10 15:16:35 +0100709 // Metalava does not differentiate between bootclasspath and classpath and has not done so for
710 // years, so it is unlikely to change any time soon.
711 combinedPaths := append(([]android.Path)(nil), bootclasspath.Paths()...)
712 combinedPaths = append(combinedPaths, classpath.Paths()...)
713 if len(combinedPaths) > 0 {
714 cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
Colin Cross2207f872021-03-24 12:39:08 -0700715 }
716
Liz Kammere09e20e2023-10-16 15:07:54 -0400717 cmd.Flag(config.MetalavaFlags)
Jihoon Kangc8313892023-09-20 00:54:47 +0000718
Colin Cross2207f872021-03-24 12:39:08 -0700719 return cmd
720}
721
Jihoon Kang3c89f042023-12-19 02:40:22 +0000722// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
723// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
724// property is defined, apply transformations and only revert the flagged apis that are not
725// enabled via release configurations and are not specified in aconfig_declarations
726func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
727
728 if len(aconfigFlagsPaths) == 0 {
729 cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
730 return
731 }
Jihoon Kang6592e872023-12-19 01:13:16 +0000732
733 releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
734 revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
735
736 var filterArgs string
737 switch stubsType {
738 // No flagged apis specific flags need to be passed to metalava when generating
739 // everything stubs
740 case Everything:
741 return
742
743 case Runtime:
744 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
745
746 case Exportable:
747 filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
748
749 }
750
751 ctx.Build(pctx, android.BuildParams{
752 Rule: gatherReleasedFlaggedApisRule,
753 Inputs: aconfigFlagsPaths,
754 Output: releasedFlaggedApisFile,
755 Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
756 Args: map[string]string{
757 "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
758 "filter_args": filterArgs,
759 },
760 })
761
762 ctx.Build(pctx, android.BuildParams{
763 Rule: generateMetalavaRevertAnnotationsRule,
764 Input: releasedFlaggedApisFile,
765 Output: revertAnnotationsFile,
766 Description: fmt.Sprintf("%s revert annotations", stubsType),
767 })
Jihoon Kang3c89f042023-12-19 02:40:22 +0000768
769 cmd.FlagWithInput("@", revertAnnotationsFile)
Jihoon Kang6592e872023-12-19 01:13:16 +0000770}
771
Jihoon Kang3c89f042023-12-19 02:40:22 +0000772func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
773 params stubsCommandParams) *android.RuleBuilderCommand {
Colin Cross2207f872021-03-24 12:39:08 -0700774 if BoolDefault(d.properties.High_mem, false) {
775 // This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
776 rule.HighMem()
777 }
778
Jihoon Kang3c89f042023-12-19 02:40:22 +0000779 if params.stubConfig.generateStubs {
780 rule.Command().Text("rm -rf").Text(params.stubsDir.String())
781 rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -0700782 }
783
Jihoon Kang3c89f042023-12-19 02:40:22 +0000784 srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
Colin Cross2207f872021-03-24 12:39:08 -0700785
Jihoon Kang3c89f042023-12-19 02:40:22 +0000786 homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
787 cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
788 params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
Colin Cross2207f872021-03-24 12:39:08 -0700789 cmd.Implicits(d.Javadoc.implicits)
790
Jihoon Kang3c89f042023-12-19 02:40:22 +0000791 d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
Colin Cross2207f872021-03-24 12:39:08 -0700792
Jihoon Kang3c89f042023-12-19 02:40:22 +0000793 if params.stubConfig.writeSdkValues {
794 d.sdkValuesFlags(ctx, cmd, params.metadataDir)
795 }
796
797 annotationParams := annotationFlagsParams{
798 migratingNullability: params.stubConfig.migratingNullability,
799 validatingNullability: params.stubConfig.validatingNullability,
800 nullabilityWarningsFile: params.nullabilityWarningsFile,
801 annotationsZip: params.annotationsZip,
802 }
803
804 d.annotationsFlags(ctx, cmd, annotationParams)
Colin Cross2207f872021-03-24 12:39:08 -0700805 d.inclusionAnnotationsFlags(ctx, cmd)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000806 d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
Colin Cross2207f872021-03-24 12:39:08 -0700807
Colin Crossbc139922021-03-25 18:33:16 -0700808 d.expandArgs(ctx, cmd)
Colin Cross2207f872021-03-24 12:39:08 -0700809
Colin Cross2207f872021-03-24 12:39:08 -0700810 for _, o := range d.Javadoc.properties.Out {
811 cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
812 }
813
Jihoon Kang3c89f042023-12-19 02:40:22 +0000814 return cmd
815}
Colin Cross2207f872021-03-24 12:39:08 -0700816
Jihoon Kang3c89f042023-12-19 02:40:22 +0000817// Sandbox rule for generating the everything stubs and other artifacts
818func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
819 srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
820 rule := android.NewRuleBuilder(pctx, ctx)
821 rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
822 android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
823 SandboxInputs()
824
825 var stubsDir android.OptionalPath
826 if params.generateStubs {
827 stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
828 d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
829 }
830
831 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +0000832 d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
833 d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000834 }
835
836 if Bool(d.properties.Annotations_enabled) {
837 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +0000838 d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000839 }
Jihoon Kangee113282024-01-23 00:16:41 +0000840 d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000841 }
842 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +0000843 d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
Jihoon Kang3c89f042023-12-19 02:40:22 +0000844 }
845
846 commonCmdParams := stubsCommandParams{
847 srcJarDir: srcJarDir,
848 stubsDir: stubsDir,
849 stubsSrcJar: d.Javadoc.stubsSrcJar,
Jihoon Kangee113282024-01-23 00:16:41 +0000850 metadataDir: d.everythingArtifacts.metadataDir,
851 apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
852 nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
853 annotationsZip: d.everythingArtifacts.annotationsZip,
Jihoon Kang3c89f042023-12-19 02:40:22 +0000854 stubConfig: params,
855 }
856
857 cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
858
859 d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
860
861 if params.generateStubs {
862 rule.Command().
863 BuiltTool("soong_zip").
864 Flag("-write_if_changed").
865 Flag("-jar").
866 FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
867 FlagWithArg("-C ", stubsDir.String()).
868 FlagWithArg("-D ", stubsDir.String())
869 }
870
871 if params.writeSdkValues {
872 rule.Command().
873 BuiltTool("soong_zip").
874 Flag("-write_if_changed").
875 Flag("-d").
Jihoon Kangee113282024-01-23 00:16:41 +0000876 FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
877 FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
878 FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
Jihoon Kang3c89f042023-12-19 02:40:22 +0000879 }
880
881 // TODO: We don't really need two separate API files, but this is a reminiscence of how
882 // we used to run metalava separately for API lint and the "last_released" check. Unify them.
883 if params.doApiLint {
884 rule.Command().Text("touch").Output(d.apiLintTimestamp)
885 }
886 if params.doCheckReleased {
887 rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
888 }
889
890 // TODO(b/183630617): rewrapper doesn't support restat rules
891 if !metalavaUseRbe(ctx) {
892 rule.Restat()
893 }
894
895 zipSyncCleanupCmd(rule, srcJarDir)
896
897 rule.Build("metalava", "metalava merged")
898}
899
900// Sandbox rule for generating the everything artifacts that are not run by
901// default but only run based on the module configurations
902func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
Colin Cross2207f872021-03-24 12:39:08 -0700903
904 // Add API lint options.
Jihoon Kang3c89f042023-12-19 02:40:22 +0000905 if doApiLint {
Colin Cross2207f872021-03-24 12:39:08 -0700906 newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
907 if newSince.Valid() {
908 cmd.FlagWithInput("--api-lint ", newSince.Path())
909 } else {
910 cmd.Flag("--api-lint")
911 }
Jihoon Kang3c89f042023-12-19 02:40:22 +0000912 d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700913 cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
914
Colin Cross0d532412021-03-25 09:38:45 -0700915 // TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
Colin Cross2207f872021-03-24 12:39:08 -0700916 if d.Name() != "android.car-system-stubs-docs" &&
917 d.Name() != "android.car-stubs-docs" {
918 cmd.Flag("--lints-as-errors")
919 cmd.Flag("--warnings-as-errors") // Most lints are actually warnings.
920 }
921
922 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000923 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
924 d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700925
926 // Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
Colin Cross2207f872021-03-24 12:39:08 -0700927 //
928 // TODO: metalava also has a slightly different message hardcoded. Should we unify this
929 // message and metalava's one?
930 msg := `$'` + // Enclose with $' ... '
931 `************************************************************\n` +
932 `Your API changes are triggering API Lint warnings or errors.\n` +
933 `To make these errors go away, fix the code according to the\n` +
934 `error and/or warning messages above.\n` +
935 `\n` +
936 `If it is not possible to do so, there are workarounds:\n` +
937 `\n` +
Aurimas Liutikasb23b7452021-05-24 18:00:37 +0000938 `1. You can suppress the errors with @SuppressLint("<id>")\n` +
939 ` where the <id> is given in brackets in the error message above.\n`
Colin Cross2207f872021-03-24 12:39:08 -0700940
941 if baselineFile.Valid() {
942 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
943 cmd.FlagWithOutput("--update-baseline:api-lint ", updatedBaselineOutput)
944
945 msg += fmt.Sprintf(``+
946 `2. You can update the baseline by executing the following\n`+
947 ` command:\n`+
Colin Cross63eeda02021-04-15 19:01:57 -0700948 ` (cd $ANDROID_BUILD_TOP && cp \\\n`+
949 ` "%s" \\\n`+
950 ` "%s")\n`+
Colin Cross2207f872021-03-24 12:39:08 -0700951 ` To submit the revised baseline.txt to the main Android\n`+
952 ` repository, you will need approval.\n`, updatedBaselineOutput, baselineFile.Path())
953 } else {
954 msg += fmt.Sprintf(``+
955 `2. You can add a baseline file of existing lint failures\n`+
956 ` to the build rule of %s.\n`, d.Name())
957 }
958 // Note the message ends with a ' (single quote), to close the $' ... ' .
959 msg += `************************************************************\n'`
960
961 cmd.FlagWithArg("--error-message:api-lint ", msg)
962 }
963
964 // Add "check released" options. (Detect incompatible API changes from the last public release)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000965 if doCheckReleased {
Colin Cross2207f872021-03-24 12:39:08 -0700966 if len(d.Javadoc.properties.Out) > 0 {
967 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
968 }
969
970 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
971 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
972 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
Jihoon Kang3c89f042023-12-19 02:40:22 +0000973 updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
Colin Cross2207f872021-03-24 12:39:08 -0700974
Jihoon Kang3c89f042023-12-19 02:40:22 +0000975 d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -0700976
977 cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
978 cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
979
980 if baselineFile.Valid() {
981 cmd.FlagWithInput("--baseline:compatibility:released ", baselineFile.Path())
982 cmd.FlagWithOutput("--update-baseline:compatibility:released ", updatedBaselineOutput)
983 }
984
985 // Note this string includes quote ($' ... '), which decodes the "\n"s.
986 msg := `$'\n******************************\n` +
987 `You have tried to change the API from what has been previously released in\n` +
988 `an SDK. Please fix the errors listed above.\n` +
989 `******************************\n'`
990
991 cmd.FlagWithArg("--error-message:compatibility:released ", msg)
992 }
993
Paul Duffin10a23c22023-08-11 22:47:31 +0100994 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
995 // Pass the current API file into metalava so it can use it as the basis for determining how to
996 // generate the output signature files (both api and removed).
997 currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
998 cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
999 }
Jihoon Kang3c89f042023-12-19 02:40:22 +00001000}
Paul Duffin10a23c22023-08-11 22:47:31 +01001001
Jihoon Kang3c89f042023-12-19 02:40:22 +00001002// Sandbox rule for generating exportable stubs and other artifacts
1003func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
1004 optionalCmdParams := stubsCommandParams{
1005 stubConfig: params,
1006 }
1007
Jihoon Kang246690a2024-02-01 21:55:01 +00001008 if params.generateStubs {
1009 d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
1010 optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
1011 }
1012
Jihoon Kang3c89f042023-12-19 02:40:22 +00001013 if params.writeSdkValues {
Jihoon Kangee113282024-01-23 00:16:41 +00001014 d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
1015 d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
1016 optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
1017 optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
Jihoon Kang3c89f042023-12-19 02:40:22 +00001018 }
1019
1020 if Bool(d.properties.Annotations_enabled) {
1021 if params.validatingNullability {
Jihoon Kangee113282024-01-23 00:16:41 +00001022 d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
1023 optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
Jihoon Kang3c89f042023-12-19 02:40:22 +00001024 }
Jihoon Kangee113282024-01-23 00:16:41 +00001025 d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
1026 optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
Jihoon Kang3c89f042023-12-19 02:40:22 +00001027 }
1028 if Bool(d.properties.Api_levels_annotations_enabled) {
Jihoon Kangee113282024-01-23 00:16:41 +00001029 d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
1030 optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
Jihoon Kang3c89f042023-12-19 02:40:22 +00001031 }
1032
1033 if params.checkApi || String(d.properties.Api_filename) != "" {
1034 filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
1035 d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1036 }
1037
1038 if params.checkApi || String(d.properties.Removed_api_filename) != "" {
1039 filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
1040 d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
1041 }
1042
1043 d.optionalStubCmd(ctx, optionalCmdParams)
1044}
1045
1046func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
1047
1048 params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
1049 rule := android.NewRuleBuilder(pctx, ctx)
1050 rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
1051 android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
1052 SandboxInputs()
1053
1054 if params.stubConfig.generateStubs {
1055 params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
1056 }
1057
1058 cmd := d.commonMetalavaStubCmd(ctx, rule, params)
1059
1060 d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
1061
1062 if params.stubConfig.doApiLint {
1063 // Pass the lint baseline file as an input to resolve the lint errors.
1064 // The exportable stubs generation does not update the lint baseline file.
1065 // Lint baseline file update is handled by the everything stubs
1066 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
1067 if baselineFile.Valid() {
1068 cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
1069 }
1070 }
1071
1072 if params.stubConfig.generateStubs {
Colin Cross2207f872021-03-24 12:39:08 -07001073 rule.Command().
1074 BuiltTool("soong_zip").
1075 Flag("-write_if_changed").
1076 Flag("-jar").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001077 FlagWithOutput("-o ", params.stubsSrcJar).
1078 FlagWithArg("-C ", params.stubsDir.String()).
1079 FlagWithArg("-D ", params.stubsDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001080 }
1081
Jihoon Kang3c89f042023-12-19 02:40:22 +00001082 if params.stubConfig.writeSdkValues {
Colin Cross2207f872021-03-24 12:39:08 -07001083 rule.Command().
1084 BuiltTool("soong_zip").
1085 Flag("-write_if_changed").
1086 Flag("-d").
Jihoon Kang3c89f042023-12-19 02:40:22 +00001087 FlagWithOutput("-o ", params.metadataZip).
1088 FlagWithArg("-C ", params.metadataDir.String()).
1089 FlagWithArg("-D ", params.metadataDir.String())
Colin Cross2207f872021-03-24 12:39:08 -07001090 }
1091
Colin Cross6aa5c402021-03-24 12:28:50 -07001092 // TODO(b/183630617): rewrapper doesn't support restat rules
Colin Crosse52c2ac2022-03-28 17:03:35 -07001093 if !metalavaUseRbe(ctx) {
1094 rule.Restat()
1095 }
Colin Cross2207f872021-03-24 12:39:08 -07001096
Jihoon Kang3c89f042023-12-19 02:40:22 +00001097 zipSyncCleanupCmd(rule, params.srcJarDir)
Colin Cross2207f872021-03-24 12:39:08 -07001098
Jihoon Kang3c89f042023-12-19 02:40:22 +00001099 rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
1100}
1101
1102func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
1103 deps := d.Javadoc.collectDeps(ctx)
1104
1105 javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
1106 generateStubs := BoolDefault(d.properties.Generate_stubs, true)
1107
1108 // Add options for the other optional tasks: API-lint and check-released.
1109 // We generate separate timestamp files for them.
1110 doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
1111 doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1112
1113 writeSdkValues := Bool(d.properties.Write_sdk_values)
1114
1115 annotationsEnabled := Bool(d.properties.Annotations_enabled)
1116
1117 migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
1118 validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
1119 String(d.properties.Validate_nullability_from_list) != "")
1120
1121 checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
1122 apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
1123
1124 stubCmdParams := stubsCommandConfigParams{
1125 javaVersion: javaVersion,
1126 deps: deps,
1127 checkApi: checkApi,
1128 generateStubs: generateStubs,
1129 doApiLint: doApiLint,
1130 doCheckReleased: doCheckReleased,
1131 writeSdkValues: writeSdkValues,
1132 migratingNullability: migratingNullability,
1133 validatingNullability: validatingNullability,
1134 }
1135 stubCmdParams.stubsType = Everything
1136 // Create default (i.e. "everything" stubs) rule for metalava
1137 d.everythingStubCmd(ctx, stubCmdParams)
1138
1139 // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
1140 // aconfig_declarations property is defined or not. If the property is not defined, the module simply
1141 // strips all flagged apis to generate the "exportable" stubs
1142 stubCmdParams.stubsType = Exportable
1143 d.exportableStubCmd(ctx, stubCmdParams)
Paul Duffinc166b682022-05-27 12:23:08 +00001144
Paul Duffine7a86642022-08-16 15:43:20 +00001145 if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
1146
1147 if len(d.Javadoc.properties.Out) > 0 {
1148 ctx.PropertyErrorf("out", "out property may not be combined with check_api")
1149 }
1150
1151 apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
1152 removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file))
1153 baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file)
1154
1155 if baselineFile.Valid() {
1156 ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
1157 }
1158
Jihoon Kang3c89f042023-12-19 02:40:22 +00001159 d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001160
1161 rule := android.NewRuleBuilder(pctx, ctx)
1162
1163 // Diff command line.
1164 // -F matches the closest "opening" line, such as "package android {"
1165 // and " public class Intent {".
1166 diff := `diff -u -F '{ *$'`
1167
1168 rule.Command().Text("( true")
1169 rule.Command().
1170 Text(diff).
1171 Input(apiFile).Input(d.apiFile)
1172
1173 rule.Command().
1174 Text(diff).
1175 Input(removedApiFile).Input(d.removedApiFile)
1176
1177 msg := fmt.Sprintf(`\n******************************\n`+
1178 `You have tried to change the API from what has been previously approved.\n\n`+
1179 `To make these errors go away, you have two choices:\n`+
1180 ` 1. You can add '@hide' javadoc comments (and remove @SystemApi/@TestApi/etc)\n`+
1181 ` to the new methods, etc. shown in the above diff.\n\n`+
1182 ` 2. You can update current.txt and/or removed.txt by executing the following command:\n`+
1183 ` m %s-update-current-api\n\n`+
1184 ` To submit the revised current.txt to the main Android repository,\n`+
1185 ` you will need approval.\n`+
Jihoon Kang3ea64672023-11-03 00:40:26 +00001186 `If your build failed due to stub validation, you can resolve the errors with\n`+
1187 `either of the two choices above and try re-building the target.\n`+
1188 `If the mismatch between the stubs and the current.txt is intended,\n`+
1189 `you can try re-building the target by executing the following command:\n`+
Jihoon Kang91bf3dd2024-01-24 00:40:23 +00001190 `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
1191 `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
Paul Duffine7a86642022-08-16 15:43:20 +00001192 `******************************\n`, ctx.ModuleName())
1193
1194 rule.Command().
1195 Text("touch").Output(d.checkCurrentApiTimestamp).
1196 Text(") || (").
1197 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1198 Text("; exit 38").
1199 Text(")")
1200
1201 rule.Build("metalavaCurrentApiCheck", "check current API")
1202
Jihoon Kang3c89f042023-12-19 02:40:22 +00001203 d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
Paul Duffine7a86642022-08-16 15:43:20 +00001204
1205 // update API rule
1206 rule = android.NewRuleBuilder(pctx, ctx)
1207
1208 rule.Command().Text("( true")
1209
1210 rule.Command().
1211 Text("cp").Flag("-f").
1212 Input(d.apiFile).Flag(apiFile.String())
1213
1214 rule.Command().
1215 Text("cp").Flag("-f").
1216 Input(d.removedApiFile).Flag(removedApiFile.String())
1217
1218 msg = "failed to update public API"
1219
1220 rule.Command().
1221 Text("touch").Output(d.updateCurrentApiTimestamp).
1222 Text(") || (").
1223 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1224 Text("; exit 38").
1225 Text(")")
1226
1227 rule.Build("metalavaCurrentApiUpdate", "update current API")
1228 }
1229
Colin Cross2207f872021-03-24 12:39:08 -07001230 if String(d.properties.Check_nullability_warnings) != "" {
Jihoon Kangee113282024-01-23 00:16:41 +00001231 if d.everythingArtifacts.nullabilityWarningsFile == nil {
Colin Cross2207f872021-03-24 12:39:08 -07001232 ctx.PropertyErrorf("check_nullability_warnings",
1233 "Cannot specify check_nullability_warnings unless validating nullability")
1234 }
1235
1236 checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
1237
Jihoon Kang3c89f042023-12-19 02:40:22 +00001238 d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
Colin Cross2207f872021-03-24 12:39:08 -07001239
1240 msg := fmt.Sprintf(`\n******************************\n`+
1241 `The warnings encountered during nullability annotation validation did\n`+
1242 `not match the checked in file of expected warnings. The diffs are shown\n`+
1243 `above. You have two options:\n`+
1244 ` 1. Resolve the differences by editing the nullability annotations.\n`+
1245 ` 2. Update the file of expected warnings by running:\n`+
1246 ` cp %s %s\n`+
1247 ` and submitting the updated file as part of your change.`,
Jihoon Kangee113282024-01-23 00:16:41 +00001248 d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
Colin Cross2207f872021-03-24 12:39:08 -07001249
1250 rule := android.NewRuleBuilder(pctx, ctx)
1251
1252 rule.Command().
1253 Text("(").
Jihoon Kangee113282024-01-23 00:16:41 +00001254 Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Colin Cross2207f872021-03-24 12:39:08 -07001255 Text("&&").
1256 Text("touch").Output(d.checkNullabilityWarningsTimestamp).
1257 Text(") || (").
1258 Text("echo").Flag("-e").Flag(`"` + msg + `"`).
1259 Text("; exit 38").
1260 Text(")")
1261
1262 rule.Build("nullabilityWarningsCheck", "nullability warnings check")
1263 }
LaMont Jonesafe7baf2024-01-09 22:47:39 +00001264 android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
Colin Cross2207f872021-03-24 12:39:08 -07001265}
1266
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001267func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
1268 api_file := d.properties.Check_api.Current.Api_file
1269 api_surface := d.properties.Api_surface
1270
1271 props := struct {
1272 Name *string
1273 Api_surface *string
1274 Api_file *string
Jihoon Kang42b589c2023-02-03 22:56:13 +00001275 Visibility []string
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001276 }{}
1277
1278 props.Name = proptools.StringPtr(d.Name() + ".api.contribution")
1279 props.Api_surface = api_surface
1280 props.Api_file = api_file
Jihoon Kang42b589c2023-02-03 22:56:13 +00001281 props.Visibility = []string{"//visibility:override", "//visibility:public"}
Jihoon Kang3198f3c2023-01-26 08:08:52 +00001282
1283 ctx.CreateModule(ApiContributionFactory, &props)
1284}
1285
Spandan Das0b555e32022-11-28 18:48:51 +00001286// TODO (b/262014796): Export the API contributions of CorePlatformApi
1287// A map to populate the api surface of a droidstub from a substring appearing in its name
1288// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
1289// use a strict naming convention
1290var (
1291 droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
1292 //public is commented out since the core libraries use public in their java_sdk_library names
1293 "intracore": android.SdkIntraCore,
1294 "intra.core": android.SdkIntraCore,
1295 "system_server": android.SdkSystemServer,
1296 "system-server": android.SdkSystemServer,
1297 "system": android.SdkSystem,
1298 "module_lib": android.SdkModule,
1299 "module-lib": android.SdkModule,
Spandan Dasda977552023-01-26 20:45:16 +00001300 "platform.api": android.SdkCorePlatform,
Spandan Das0b555e32022-11-28 18:48:51 +00001301 "test": android.SdkTest,
Spandan Das4ac2aed2022-12-28 01:54:29 +00001302 "toolchain": android.SdkToolchain,
Spandan Das0b555e32022-11-28 18:48:51 +00001303 }
1304)
1305
Colin Cross2207f872021-03-24 12:39:08 -07001306func StubsDefaultsFactory() android.Module {
1307 module := &DocDefaults{}
1308
1309 module.AddProperties(
1310 &JavadocProperties{},
1311 &DroidstubsProperties{},
1312 )
1313
1314 android.InitDefaultsModule(module)
1315
1316 return module
1317}
1318
1319var _ android.PrebuiltInterface = (*PrebuiltStubsSources)(nil)
1320
1321type PrebuiltStubsSourcesProperties struct {
1322 Srcs []string `android:"path"`
Spandan Das23956d12024-01-19 00:22:22 +00001323
1324 // Name of the source soong module that gets shadowed by this prebuilt
1325 // If unspecified, follows the naming convention that the source module of
1326 // the prebuilt is Name() without "prebuilt_" prefix
1327 Source_module_name *string
1328
1329 // Non-nil if this prebuilt stub srcs module was dynamically created by a java_sdk_library_import
1330 // The name is the undecorated name of the java_sdk_library as it appears in the blueprint file
1331 // (without any prebuilt_ prefix)
1332 Created_by_java_sdk_library_name *string `blueprint:"mutated"`
1333}
1334
1335func (j *PrebuiltStubsSources) BaseModuleName() string {
1336 return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
1337}
1338
1339func (j *PrebuiltStubsSources) CreatedByJavaSdkLibraryName() *string {
1340 return j.properties.Created_by_java_sdk_library_name
Colin Cross2207f872021-03-24 12:39:08 -07001341}
1342
1343type PrebuiltStubsSources struct {
1344 android.ModuleBase
1345 android.DefaultableModuleBase
Spandan Das2cc80ba2023-10-27 17:21:52 +00001346 embeddableInModuleAndImport
1347
Colin Cross2207f872021-03-24 12:39:08 -07001348 prebuilt android.Prebuilt
Colin Cross2207f872021-03-24 12:39:08 -07001349
1350 properties PrebuiltStubsSourcesProperties
1351
kgui67007242022-01-25 13:50:25 +08001352 stubsSrcJar android.Path
Colin Cross2207f872021-03-24 12:39:08 -07001353}
1354
1355func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
1356 switch tag {
Jihoon Kangfa4a90d2023-12-20 02:53:38 +00001357 // prebuilt droidstubs does not output "exportable" stubs.
1358 // Output the "everything" stubs srcjar file if the tag is ".exportable".
1359 case "", ".exportable":
Colin Cross2207f872021-03-24 12:39:08 -07001360 return android.Paths{p.stubsSrcJar}, nil
1361 default:
1362 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
1363 }
1364}
1365
Jihoon Kangee113282024-01-23 00:16:41 +00001366func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
1367 return d.stubsSrcJar, nil
Colin Cross2207f872021-03-24 12:39:08 -07001368}
1369
1370func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Colin Cross2207f872021-03-24 12:39:08 -07001371 if len(p.properties.Srcs) != 1 {
Anton Hansson86758ac2021-11-03 14:44:12 +00001372 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 -07001373 return
1374 }
1375
Anton Hansson86758ac2021-11-03 14:44:12 +00001376 src := p.properties.Srcs[0]
1377 if filepath.Ext(src) == ".srcjar" {
1378 // This is a srcjar. We can use it directly.
1379 p.stubsSrcJar = android.PathForModuleSrc(ctx, src)
1380 } else {
1381 outPath := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar")
Colin Cross2207f872021-03-24 12:39:08 -07001382
Anton Hansson86758ac2021-11-03 14:44:12 +00001383 // This is a directory. Glob the contents just in case the directory does not exist.
1384 srcGlob := src + "/**/*"
1385 srcPaths := android.PathsForModuleSrc(ctx, []string{srcGlob})
Colin Cross2207f872021-03-24 12:39:08 -07001386
Anton Hansson86758ac2021-11-03 14:44:12 +00001387 // Although PathForModuleSrc can return nil if either the path doesn't exist or
1388 // the path components are invalid it won't in this case because no components
1389 // are specified and the module directory must exist in order to get this far.
1390 srcDir := android.PathForModuleSrc(ctx).(android.SourcePath).Join(ctx, src)
Colin Cross2207f872021-03-24 12:39:08 -07001391
Anton Hansson86758ac2021-11-03 14:44:12 +00001392 rule := android.NewRuleBuilder(pctx, ctx)
1393 rule.Command().
1394 BuiltTool("soong_zip").
1395 Flag("-write_if_changed").
1396 Flag("-jar").
1397 FlagWithOutput("-o ", outPath).
1398 FlagWithArg("-C ", srcDir.String()).
1399 FlagWithRspFileInputList("-r ", outPath.ReplaceExtension(ctx, "rsp"), srcPaths)
1400 rule.Restat()
1401 rule.Build("zip src", "Create srcjar from prebuilt source")
1402 p.stubsSrcJar = outPath
1403 }
Colin Cross2207f872021-03-24 12:39:08 -07001404}
1405
1406func (p *PrebuiltStubsSources) Prebuilt() *android.Prebuilt {
1407 return &p.prebuilt
1408}
1409
1410func (p *PrebuiltStubsSources) Name() string {
1411 return p.prebuilt.Name(p.ModuleBase.Name())
1412}
1413
1414// prebuilt_stubs_sources imports a set of java source files as if they were
1415// generated by droidstubs.
1416//
1417// By default, a prebuilt_stubs_sources has a single variant that expects a
1418// set of `.java` files generated by droidstubs.
1419//
1420// Specifying `host_supported: true` will produce two variants, one for use as a dependency of device modules and one
1421// for host modules.
1422//
1423// Intended only for use by sdk snapshots.
1424func PrebuiltStubsSourcesFactory() android.Module {
1425 module := &PrebuiltStubsSources{}
1426
1427 module.AddProperties(&module.properties)
Spandan Das2cc80ba2023-10-27 17:21:52 +00001428 module.initModuleAndImport(module)
Colin Cross2207f872021-03-24 12:39:08 -07001429
1430 android.InitPrebuiltModule(module, &module.properties.Srcs)
Colin Cross2207f872021-03-24 12:39:08 -07001431 InitDroiddocModule(module, android.HostAndDeviceSupported)
1432 return module
1433}