blob: 573fc8ef556872bfadc0277882ecf7ae5e93acbc [file] [log] [blame]
Jiyong Parkc678ad32018-04-10 13:07:10 +09001// Copyright 2018 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 "android/soong/android"
19 "android/soong/genrule"
20 "fmt"
Jiyong Park82484c02018-04-23 21:41:26 +090021 "io"
Jiyong Parkc678ad32018-04-10 13:07:10 +090022 "path"
Jiyong Park82484c02018-04-23 21:41:26 +090023 "sort"
Jiyong Parkc678ad32018-04-10 13:07:10 +090024 "strings"
Jiyong Park82484c02018-04-23 21:41:26 +090025 "sync"
Jiyong Parkc678ad32018-04-10 13:07:10 +090026
27 "github.com/google/blueprint"
28 "github.com/google/blueprint/proptools"
29)
30
31var (
32 sdkStubsLibrarySuffix = ".stubs"
33 sdkSystemApiSuffix = ".system"
Jiyong Parkdf130542018-04-27 16:29:21 +090034 sdkTestApiSuffix = ".test"
Jiyong Parkc678ad32018-04-10 13:07:10 +090035 sdkDocsSuffix = ".docs"
36 sdkImplLibrarySuffix = ".impl"
37 sdkXmlFileSuffix = ".xml"
38)
39
40type stubsLibraryDependencyTag struct {
41 blueprint.BaseDependencyTag
42 name string
43}
44
45var (
46 publicApiStubsTag = dependencyTag{name: "public"}
47 systemApiStubsTag = dependencyTag{name: "system"}
Jiyong Parkdf130542018-04-27 16:29:21 +090048 testApiStubsTag = dependencyTag{name: "test"}
Sundong Ahn57368eb2018-07-06 11:20:23 +090049 implLibTag = dependencyTag{name: "platform"}
Sundong Ahn20e998b2018-07-24 11:19:26 +090050 publicApiFileTag = dependencyTag{name: "publicApi"}
51 systemApiFileTag = dependencyTag{name: "systemApi"}
52 testApiFileTag = dependencyTag{name: "testApi"}
Jiyong Parkdf130542018-04-27 16:29:21 +090053)
54
55type apiScope int
56
57const (
58 apiScopePublic apiScope = iota
59 apiScopeSystem
60 apiScopeTest
Jiyong Parkc678ad32018-04-10 13:07:10 +090061)
62
Jiyong Park82484c02018-04-23 21:41:26 +090063var (
64 javaSdkLibrariesLock sync.Mutex
65)
66
Jiyong Parkc678ad32018-04-10 13:07:10 +090067// java_sdk_library is to make a Java library that implements optional platform APIs to apps.
68// It is actually a wrapper of several modules: 1) stubs library that clients are linked against
69// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime
70// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the
71// classpath at runtime if requested via <uses-library>.
72//
73// TODO: these are big features that are currently missing
Jiyong Park1be96912018-05-28 18:02:19 +090074// 1) disallowing linking to the runtime shared lib
75// 2) HTML generation
Jiyong Parkc678ad32018-04-10 13:07:10 +090076
77func init() {
78 android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
79
80 android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
81 ctx.TopDown("java_sdk_library", sdkLibraryMutator).Parallel()
82 })
Jiyong Park82484c02018-04-23 21:41:26 +090083
84 android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
85 javaSdkLibraries := javaSdkLibraries(ctx.Config())
86 sort.Strings(*javaSdkLibraries)
87 ctx.Strict("JAVA_SDK_LIBRARIES", strings.Join(*javaSdkLibraries, " "))
88 })
Jiyong Parkc678ad32018-04-10 13:07:10 +090089}
90
91type sdkLibraryProperties struct {
92 // list of source files used to compile the Java module. May be .java, .logtags, .proto,
93 // or .aidl files.
94 Srcs []string `android:"arch_variant"`
95
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +090096 // list of optional source files that are part of API but not part of runtime library.
97 Api_srcs []string `android:"arch_variant"`
98
Jiyong Parkc678ad32018-04-10 13:07:10 +090099 // list of of java libraries that will be in the classpath
100 Libs []string `android:"arch_variant"`
101
102 // list of java libraries that will be compiled into the resulting runtime jar.
103 // These libraries are not compiled into the stubs jar.
104 Static_libs []string `android:"arch_variant"`
105
Sundong Ahnf043cf62018-06-25 16:04:37 +0900106 // List of Java libraries that will be in the classpath when building stubs
107 Stub_only_libs []string `android:"arch_variant"`
108
Jiyong Parkc678ad32018-04-10 13:07:10 +0900109 // list of package names that will be documented and publicized as API
110 Api_packages []string
111
Jiyong Park5a2c9d72018-05-01 22:25:41 +0900112 // list of package names that must be hidden from the API
113 Hidden_api_packages []string
114
Jiyong Parkb5b709f2018-06-15 10:38:59 +0900115 Errorprone struct {
116 // List of javac flags that should only be used when running errorprone.
117 Javacflags []string
118 }
119
Sundong Ahndd567f92018-07-31 17:19:11 +0900120 // Additional droiddoc options
121 Droiddoc_options []string
122
123 // If set to true, compile dex regardless of installable. Defaults to false.
124 // This applies to the stubs lib.
125 Compile_dex *bool
126
127 // the sub dirs under srcs_lib_whitelist_dirs will be scanned for java srcs.
128 // Defaults to "android.annotation".
129 Srcs_lib_whitelist_pkgs []string
130
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900131 // if set to true, create stubs through Metalava instead of Doclava. Javadoc/Doclava is
132 // currently still used for documentation generation, and will be replaced by Dokka soon.
133 // Defaults to true.
134 Metalava_enabled *bool
135
Jiyong Parkc678ad32018-04-10 13:07:10 +0900136 // TODO: determines whether to create HTML doc or not
137 //Html_doc *bool
138}
139
140type sdkLibrary struct {
141 android.ModuleBase
142 android.DefaultableModuleBase
143
Jiyong Park441a47d2018-05-01 23:33:08 +0900144 properties sdkLibraryProperties
145 deviceProperties CompilerDeviceProperties
Jiyong Parkc678ad32018-04-10 13:07:10 +0900146
147 publicApiStubsPath android.Paths
148 systemApiStubsPath android.Paths
Jiyong Parkdf130542018-04-27 16:29:21 +0900149 testApiStubsPath android.Paths
Sundong Ahn57368eb2018-07-06 11:20:23 +0900150 implLibPath android.Paths
Sundong Ahn241cd372018-07-13 16:16:44 +0900151
152 publicApiStubsImplPath android.Paths
153 systemApiStubsImplPath android.Paths
154 testApiStubsImplPath android.Paths
155 implLibImplPath android.Paths
Sundong Ahn20e998b2018-07-24 11:19:26 +0900156
157 publicApiFilePath android.Path
158 systemApiFilePath android.Path
159 testApiFilePath android.Path
Jiyong Parkc678ad32018-04-10 13:07:10 +0900160}
161
162func (module *sdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
163 // Add dependencies to the stubs library
Colin Cross42d48b72018-08-29 14:10:52 -0700164 ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
165 ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
166 ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
167 ctx.AddVariationDependencies(nil, implLibTag, module.implName())
Sundong Ahn20e998b2018-07-24 11:19:26 +0900168
Colin Cross42d48b72018-08-29 14:10:52 -0700169 ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
170 ctx.AddVariationDependencies(nil, systemApiFileTag, module.docsName(apiScopeSystem))
171 ctx.AddVariationDependencies(nil, testApiFileTag, module.docsName(apiScopeTest))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900172}
173
174func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Sundong Ahn57368eb2018-07-06 11:20:23 +0900175 // Record the paths to the header jars of the library (stubs and impl).
Jiyong Parkc678ad32018-04-10 13:07:10 +0900176 // When this java_sdk_library is dependened from others via "libs" property,
177 // the recorded paths will be returned depending on the link type of the caller.
178 ctx.VisitDirectDeps(func(to android.Module) {
179 otherName := ctx.OtherModuleName(to)
180 tag := ctx.OtherModuleDependencyTag(to)
181
Sundong Ahn57368eb2018-07-06 11:20:23 +0900182 if lib, ok := to.(Dependency); ok {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900183 switch tag {
184 case publicApiStubsTag:
Sundong Ahn57368eb2018-07-06 11:20:23 +0900185 module.publicApiStubsPath = lib.HeaderJars()
Sundong Ahn241cd372018-07-13 16:16:44 +0900186 module.publicApiStubsImplPath = lib.ImplementationJars()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900187 case systemApiStubsTag:
Sundong Ahn57368eb2018-07-06 11:20:23 +0900188 module.systemApiStubsPath = lib.HeaderJars()
Sundong Ahn241cd372018-07-13 16:16:44 +0900189 module.systemApiStubsImplPath = lib.ImplementationJars()
Jiyong Parkdf130542018-04-27 16:29:21 +0900190 case testApiStubsTag:
Sundong Ahn57368eb2018-07-06 11:20:23 +0900191 module.testApiStubsPath = lib.HeaderJars()
Sundong Ahn241cd372018-07-13 16:16:44 +0900192 module.testApiStubsImplPath = lib.ImplementationJars()
Sundong Ahn57368eb2018-07-06 11:20:23 +0900193 case implLibTag:
194 module.implLibPath = lib.HeaderJars()
Sundong Ahn241cd372018-07-13 16:16:44 +0900195 module.implLibImplPath = lib.ImplementationJars()
Jiyong Parkc678ad32018-04-10 13:07:10 +0900196 default:
197 ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
198 }
199 }
Sundong Ahn20e998b2018-07-24 11:19:26 +0900200 if doc, ok := to.(ApiFilePath); ok {
201 switch tag {
202 case publicApiFileTag:
203 module.publicApiFilePath = doc.ApiFilePath()
204 case systemApiFileTag:
205 module.systemApiFilePath = doc.ApiFilePath()
206 case testApiFileTag:
207 module.testApiFilePath = doc.ApiFilePath()
208 default:
209 ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
210 }
211 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900212 })
213}
214
Jiyong Park82484c02018-04-23 21:41:26 +0900215func (module *sdkLibrary) AndroidMk() android.AndroidMkData {
Jiyong Park82484c02018-04-23 21:41:26 +0900216 return android.AndroidMkData{
217 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
Jiyong Park90078382018-05-02 19:30:15 +0900218 // Create a phony module that installs the impl library, for the case when this lib is
219 // in PRODUCT_PACKAGES.
Jiyong Park82484c02018-04-23 21:41:26 +0900220 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
221 fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
222 fmt.Fprintln(w, "LOCAL_MODULE :=", name)
223 fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName())
224 fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900225 owner := module.ModuleBase.Owner()
226 if owner == "" {
227 owner = "android"
228 }
Jiyong Park90078382018-05-02 19:30:15 +0900229 // Create dist rules to install the stubs libs to the dist dir
Jiyong Parkb674a522018-05-06 07:53:02 +0900230 if len(module.publicApiStubsPath) == 1 {
231 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
Colin Crossac502722018-11-21 20:33:56 -0800232 module.publicApiStubsImplPath.Strings()[0]+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900233 ":"+path.Join("apistubs", owner, "public",
234 module.BaseModuleName()+".jar")+")")
Jiyong Parkb674a522018-05-06 07:53:02 +0900235 }
236 if len(module.systemApiStubsPath) == 1 {
237 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
Colin Crossac502722018-11-21 20:33:56 -0800238 module.systemApiStubsImplPath.Strings()[0]+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900239 ":"+path.Join("apistubs", owner, "system",
240 module.BaseModuleName()+".jar")+")")
Jiyong Parkb674a522018-05-06 07:53:02 +0900241 }
242 if len(module.testApiStubsPath) == 1 {
243 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
Colin Crossac502722018-11-21 20:33:56 -0800244 module.testApiStubsImplPath.Strings()[0]+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900245 ":"+path.Join("apistubs", owner, "test",
246 module.BaseModuleName()+".jar")+")")
Jiyong Parkb674a522018-05-06 07:53:02 +0900247 }
Sundong Ahn20e998b2018-07-24 11:19:26 +0900248 if module.publicApiFilePath != nil {
249 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
250 module.publicApiFilePath.String()+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900251 ":"+path.Join("apistubs", owner, "public", "api",
Sundong Ahn20e998b2018-07-24 11:19:26 +0900252 module.BaseModuleName()+".txt")+")")
253 }
254 if module.systemApiFilePath != nil {
255 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
256 module.systemApiFilePath.String()+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900257 ":"+path.Join("apistubs", owner, "system", "api",
Sundong Ahn20e998b2018-07-24 11:19:26 +0900258 module.BaseModuleName()+".txt")+")")
259 }
260 if module.testApiFilePath != nil {
261 fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
262 module.testApiFilePath.String()+
Sundong Ahn4fd04bb2018-08-31 18:01:37 +0900263 ":"+path.Join("apistubs", owner, "test", "api",
Sundong Ahn20e998b2018-07-24 11:19:26 +0900264 module.BaseModuleName()+".txt")+")")
265 }
Jiyong Park82484c02018-04-23 21:41:26 +0900266 },
267 }
268}
269
Jiyong Parkc678ad32018-04-10 13:07:10 +0900270// Module name of the stubs library
Jiyong Parkdf130542018-04-27 16:29:21 +0900271func (module *sdkLibrary) stubsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900272 stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900273 switch apiScope {
274 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900275 stubsName = stubsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900276 case apiScopeTest:
277 stubsName = stubsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900278 }
279 return stubsName
280}
281
282// Module name of the docs
Jiyong Parkdf130542018-04-27 16:29:21 +0900283func (module *sdkLibrary) docsName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900284 docsName := module.BaseModuleName() + sdkDocsSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900285 switch apiScope {
286 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900287 docsName = docsName + sdkSystemApiSuffix
Jiyong Parkdf130542018-04-27 16:29:21 +0900288 case apiScopeTest:
289 docsName = docsName + sdkTestApiSuffix
Jiyong Parkc678ad32018-04-10 13:07:10 +0900290 }
291 return docsName
292}
293
294// Module name of the runtime implementation library
295func (module *sdkLibrary) implName() string {
296 return module.BaseModuleName() + sdkImplLibrarySuffix
297}
298
299// File path to the runtime implementation library
300func (module *sdkLibrary) implPath() string {
301 partition := "system"
302 if module.SocSpecific() {
303 partition = "vendor"
304 } else if module.DeviceSpecific() {
305 partition = "odm"
306 } else if module.ProductSpecific() {
307 partition = "product"
308 }
309 return "/" + partition + "/framework/" + module.implName() + ".jar"
310}
311
312// Module name of the XML file for the lib
313func (module *sdkLibrary) xmlFileName() string {
314 return module.BaseModuleName() + sdkXmlFileSuffix
315}
316
317// SDK version that the stubs library is built against. Note that this is always
318// *current. Older stubs library built with a numberd SDK version is created from
319// the prebuilt jar.
Jiyong Parkdf130542018-04-27 16:29:21 +0900320func (module *sdkLibrary) sdkVersion(apiScope apiScope) string {
321 switch apiScope {
322 case apiScopePublic:
323 return "current"
324 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900325 return "system_current"
Jiyong Parkdf130542018-04-27 16:29:21 +0900326 case apiScopeTest:
327 return "test_current"
328 default:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900329 return "current"
330 }
331}
332
333// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
334// api file for the current source
335// TODO: remove this when apicheck is done in soong
Jiyong Parkdf130542018-04-27 16:29:21 +0900336func (module *sdkLibrary) apiTagName(apiScope apiScope) string {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900337 apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
Jiyong Parkdf130542018-04-27 16:29:21 +0900338 switch apiScope {
339 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900340 apiTagName = apiTagName + "_SYSTEM"
Jiyong Parkdf130542018-04-27 16:29:21 +0900341 case apiScopeTest:
342 apiTagName = apiTagName + "_TEST"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900343 }
344 return apiTagName
345}
346
Jiyong Park58c518b2018-05-12 22:29:12 +0900347func (module *sdkLibrary) latestApiFilegroupName(apiScope apiScope) string {
348 name := ":" + module.BaseModuleName() + ".api."
Jiyong Parkdf130542018-04-27 16:29:21 +0900349 switch apiScope {
Jiyong Park58c518b2018-05-12 22:29:12 +0900350 case apiScopePublic:
351 name = name + "public"
Jiyong Parkdf130542018-04-27 16:29:21 +0900352 case apiScopeSystem:
Jiyong Park58c518b2018-05-12 22:29:12 +0900353 name = name + "system"
Jiyong Parkdf130542018-04-27 16:29:21 +0900354 case apiScopeTest:
Jiyong Park58c518b2018-05-12 22:29:12 +0900355 name = name + "test"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900356 }
Jiyong Park58c518b2018-05-12 22:29:12 +0900357 name = name + ".latest"
358 return name
359}
Jiyong Parkc678ad32018-04-10 13:07:10 +0900360
Jiyong Park58c518b2018-05-12 22:29:12 +0900361func (module *sdkLibrary) latestRemovedApiFilegroupName(apiScope apiScope) string {
362 name := ":" + module.BaseModuleName() + "-removed.api."
363 switch apiScope {
364 case apiScopePublic:
365 name = name + "public"
366 case apiScopeSystem:
367 name = name + "system"
368 case apiScopeTest:
369 name = name + "test"
370 }
371 name = name + ".latest"
372 return name
Jiyong Parkc678ad32018-04-10 13:07:10 +0900373}
374
375// Creates a static java library that has API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900376func (module *sdkLibrary) createStubsLibrary(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900377 props := struct {
378 Name *string
379 Srcs []string
380 Sdk_version *string
Sundong Ahnf043cf62018-06-25 16:04:37 +0900381 Libs []string
Jiyong Parkc678ad32018-04-10 13:07:10 +0900382 Soc_specific *bool
383 Device_specific *bool
384 Product_specific *bool
Sundong Ahndd567f92018-07-31 17:19:11 +0900385 Compile_dex *bool
Jiyong Parkc678ad32018-04-10 13:07:10 +0900386 Product_variables struct {
387 Unbundled_build struct {
388 Enabled *bool
389 }
Jiyong Park82484c02018-04-23 21:41:26 +0900390 Pdk struct {
391 Enabled *bool
392 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900393 }
394 }{}
395
Jiyong Parkdf130542018-04-27 16:29:21 +0900396 props.Name = proptools.StringPtr(module.stubsName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900397 // sources are generated from the droiddoc
Jiyong Parkdf130542018-04-27 16:29:21 +0900398 props.Srcs = []string{":" + module.docsName(apiScope)}
399 props.Sdk_version = proptools.StringPtr(module.sdkVersion(apiScope))
Sundong Ahnf043cf62018-06-25 16:04:37 +0900400 props.Libs = module.properties.Stub_only_libs
Jiyong Parkc678ad32018-04-10 13:07:10 +0900401 // Unbundled apps will use the prebult one from /prebuilts/sdk
402 props.Product_variables.Unbundled_build.Enabled = proptools.BoolPtr(false)
Jiyong Park82484c02018-04-23 21:41:26 +0900403 props.Product_variables.Pdk.Enabled = proptools.BoolPtr(false)
Sundong Ahndd567f92018-07-31 17:19:11 +0900404 if module.properties.Compile_dex != nil {
405 props.Compile_dex = module.properties.Compile_dex
406 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900407
408 if module.SocSpecific() {
409 props.Soc_specific = proptools.BoolPtr(true)
410 } else if module.DeviceSpecific() {
411 props.Device_specific = proptools.BoolPtr(true)
412 } else if module.ProductSpecific() {
413 props.Product_specific = proptools.BoolPtr(true)
414 }
415
Colin Cross9ae1b922018-06-26 17:59:05 -0700416 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900417}
418
419// Creates a droiddoc module that creates stubs source files from the given full source
420// files
Jiyong Parkdf130542018-04-27 16:29:21 +0900421func (module *sdkLibrary) createDocs(mctx android.TopDownMutatorContext, apiScope apiScope) {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900422 props := struct {
423 Name *string
424 Srcs []string
Jiyong Parkc678ad32018-04-10 13:07:10 +0900425 Installable *bool
426 Srcs_lib *string
427 Srcs_lib_whitelist_dirs []string
428 Srcs_lib_whitelist_pkgs []string
429 Libs []string
430 Args *string
431 Api_tag_name *string
432 Api_filename *string
433 Removed_api_filename *string
Jiyong Park58c518b2018-05-12 22:29:12 +0900434 Check_api struct {
435 Current ApiToCheck
436 Last_released ApiToCheck
437 }
Sundong Ahn1b92c822018-05-29 11:35:17 +0900438 Aidl struct {
439 Include_dirs []string
440 Local_include_dirs []string
441 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900442 }{}
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900443 droiddocProps := struct {
444 Custom_template *string
445 }{}
Jiyong Parkc678ad32018-04-10 13:07:10 +0900446
Jiyong Parkdf130542018-04-27 16:29:21 +0900447 props.Name = proptools.StringPtr(module.docsName(apiScope))
Jiyong Parkbaaf9dd2018-05-02 01:35:27 +0900448 props.Srcs = append(props.Srcs, module.properties.Srcs...)
449 props.Srcs = append(props.Srcs, module.properties.Api_srcs...)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900450 props.Installable = proptools.BoolPtr(false)
Sundong Ahne6f0b052018-06-05 16:46:14 +0900451 // A droiddoc module has only one Libs property and doesn't distinguish between
452 // shared libs and static libs. So we need to add both of these libs to Libs property.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900453 props.Libs = module.properties.Libs
Sundong Ahne6f0b052018-06-05 16:46:14 +0900454 props.Libs = append(props.Libs, module.properties.Static_libs...)
Sundong Ahn1b92c822018-05-29 11:35:17 +0900455 props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
456 props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
Jiyong Parkc678ad32018-04-10 13:07:10 +0900457
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900458 if module.properties.Metalava_enabled == nil {
459 module.properties.Metalava_enabled = proptools.BoolPtr(true)
460 }
461
462 droiddocArgs := ""
463 if Bool(module.properties.Metalava_enabled) == true {
464 droiddocArgs = " --stub-packages " + strings.Join(module.properties.Api_packages, ":") +
465 " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " --hide-package ") +
466 " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
467 " --hide MissingPermission --hide BroadcastBehavior " +
468 "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
469 "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo"
470 } else {
471 droiddocProps.Custom_template = proptools.StringPtr("droiddoc-templates-sdk")
472 droiddocArgs = " -stubpackages " + strings.Join(module.properties.Api_packages, ":") +
473 " " + android.JoinWithPrefix(module.properties.Hidden_api_packages, " -hidePackage ") +
474 " " + android.JoinWithPrefix(module.properties.Droiddoc_options, " ") +
475 " -hide 110 -hide 111 -hide 113 -hide 121 -hide 125 -hide 126 -hide 127 -hide 128 -nodocs"
476 }
477
Jiyong Parkdf130542018-04-27 16:29:21 +0900478 switch apiScope {
479 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900480 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.SystemApi"
Jiyong Parkdf130542018-04-27 16:29:21 +0900481 case apiScopeTest:
482 droiddocArgs = droiddocArgs + " -showAnnotation android.annotation.TestApi"
Jiyong Parkc678ad32018-04-10 13:07:10 +0900483 }
484 props.Args = proptools.StringPtr(droiddocArgs)
485
486 // List of APIs identified from the provided source files are created. They are later
487 // compared against to the not-yet-released (a.k.a current) list of APIs and to the
488 // last-released (a.k.a numbered) list of API.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900489 currentApiFileName := "current.txt"
490 removedApiFileName := "removed.txt"
Jiyong Parkdf130542018-04-27 16:29:21 +0900491 switch apiScope {
492 case apiScopeSystem:
Jiyong Parkc678ad32018-04-10 13:07:10 +0900493 currentApiFileName = "system-" + currentApiFileName
494 removedApiFileName = "system-" + removedApiFileName
Jiyong Parkdf130542018-04-27 16:29:21 +0900495 case apiScopeTest:
496 currentApiFileName = "test-" + currentApiFileName
497 removedApiFileName = "test-" + removedApiFileName
Jiyong Parkc678ad32018-04-10 13:07:10 +0900498 }
499 currentApiFileName = path.Join("api", currentApiFileName)
500 removedApiFileName = path.Join("api", removedApiFileName)
Jiyong Park58c518b2018-05-12 22:29:12 +0900501 // TODO(jiyong): remove these three props
Jiyong Parkdf130542018-04-27 16:29:21 +0900502 props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
Jiyong Parkc678ad32018-04-10 13:07:10 +0900503 props.Api_filename = proptools.StringPtr(currentApiFileName)
504 props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
505
Jiyong Park58c518b2018-05-12 22:29:12 +0900506 // check against the not-yet-release API
507 props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
508 props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
Jiyong Park58c518b2018-05-12 22:29:12 +0900509
510 // check against the latest released API
511 props.Check_api.Last_released.Api_file = proptools.StringPtr(
512 module.latestApiFilegroupName(apiScope))
513 props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
514 module.latestRemovedApiFilegroupName(apiScope))
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900515 if Bool(module.properties.Metalava_enabled) == false {
516 // any change is reported as error
517 props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
518 "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
519 "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
520 "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
Jiyong Park58c518b2018-05-12 22:29:12 +0900521
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900522 // backward incompatible changes are reported as error
523 props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
524 "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
525 "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
526 "-error 15 -error 16 -error 17 -error 18")
527
528 // Include the part of the framework source. This is required for the case when
529 // API class is extending from the framework class. In that case, doclava needs
530 // to know whether the base class is hidden or not. Since that information is
531 // encoded as @hide string in the comment, we need source files for the classes,
532 // not the compiled ones.
533 props.Srcs_lib = proptools.StringPtr("framework")
534 props.Srcs_lib_whitelist_dirs = []string{"core/java"}
535
536 // Add android.annotation package to give access to the framework-defined
537 // annotations such as SystemApi, NonNull, etc.
538 if module.properties.Srcs_lib_whitelist_pkgs != nil {
539 props.Srcs_lib_whitelist_pkgs = module.properties.Srcs_lib_whitelist_pkgs
540 } else {
541 props.Srcs_lib_whitelist_pkgs = []string{"android.annotation"}
542 }
Sundong Ahndd567f92018-07-31 17:19:11 +0900543 }
Jiyong Park82484c02018-04-23 21:41:26 +0900544 // These libs are required by doclava to parse the framework sources add via
545 // Src_lib and Src_lib_whitelist_* properties just above.
Jiyong Parkc678ad32018-04-10 13:07:10 +0900546 // If we don't add them to the classpath, errors messages are generated by doclava,
547 // though they don't break the build.
Neil Fuller1fee9f32018-10-04 11:45:49 +0100548 props.Libs = append(props.Libs, "framework")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900549
Sundong Ahnfb2721f2018-09-17 13:23:09 +0900550 if Bool(module.properties.Metalava_enabled) == true {
551 mctx.CreateModule(android.ModuleFactoryAdaptor(DroidstubsFactory), &props)
552 } else {
553 mctx.CreateModule(android.ModuleFactoryAdaptor(DroiddocFactory), &props, &droiddocProps)
554 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900555}
556
557// Creates the runtime library. This is not directly linkable from other modules.
558func (module *sdkLibrary) createImplLibrary(mctx android.TopDownMutatorContext) {
559 props := struct {
560 Name *string
561 Srcs []string
562 Libs []string
563 Static_libs []string
564 Soc_specific *bool
565 Device_specific *bool
566 Product_specific *bool
Colin Cross9ae1b922018-06-26 17:59:05 -0700567 Installable *bool
Jiyong Parkc678ad32018-04-10 13:07:10 +0900568 Required []string
Jiyong Parkb5b709f2018-06-15 10:38:59 +0900569 Errorprone struct {
570 Javacflags []string
571 }
Jiyong Parkc678ad32018-04-10 13:07:10 +0900572 }{}
573
574 props.Name = proptools.StringPtr(module.implName())
575 props.Srcs = module.properties.Srcs
576 props.Libs = module.properties.Libs
577 props.Static_libs = module.properties.Static_libs
Colin Cross9ae1b922018-06-26 17:59:05 -0700578 props.Installable = proptools.BoolPtr(true)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900579 // XML file is installed along with the impl lib
580 props.Required = []string{module.xmlFileName()}
Jiyong Parkb5b709f2018-06-15 10:38:59 +0900581 props.Errorprone.Javacflags = module.properties.Errorprone.Javacflags
Jiyong Parkc678ad32018-04-10 13:07:10 +0900582
583 if module.SocSpecific() {
584 props.Soc_specific = proptools.BoolPtr(true)
585 } else if module.DeviceSpecific() {
586 props.Device_specific = proptools.BoolPtr(true)
587 } else if module.ProductSpecific() {
588 props.Product_specific = proptools.BoolPtr(true)
589 }
590
Colin Cross9ae1b922018-06-26 17:59:05 -0700591 mctx.CreateModule(android.ModuleFactoryAdaptor(LibraryFactory), &props, &module.deviceProperties)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900592}
593
594// Creates the xml file that publicizes the runtime library
595func (module *sdkLibrary) createXmlFile(mctx android.TopDownMutatorContext) {
596 template := `
597<?xml version="1.0" encoding="utf-8"?>
598<!-- Copyright (C) 2018 The Android Open Source Project
599
600 Licensed under the Apache License, Version 2.0 (the "License");
601 you may not use this file except in compliance with the License.
602 You may obtain a copy of the License at
603
604 http://www.apache.org/licenses/LICENSE-2.0
605
606 Unless required by applicable law or agreed to in writing, software
607 distributed under the License is distributed on an "AS IS" BASIS,
608 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
609 See the License for the specific language governing permissions and
610 limitations under the License.
611-->
612
613<permissions>
614 <library name="%s" file="%s"/>
615</permissions>
616`
617 // genrule to generate the xml file content from the template above
618 // TODO: preserve newlines in the generate xml file. Newlines are being squashed
619 // in the ninja file. Do we need to have an external tool for this?
620 xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath())
621 genruleProps := struct {
622 Name *string
623 Cmd *string
624 Out []string
625 }{}
626 genruleProps.Name = proptools.StringPtr(module.xmlFileName() + "-gen")
627 genruleProps.Cmd = proptools.StringPtr("echo '" + xmlContent + "' > $(out)")
628 genruleProps.Out = []string{module.xmlFileName()}
629 mctx.CreateModule(android.ModuleFactoryAdaptor(genrule.GenRuleFactory), &genruleProps)
630
631 // creates a prebuilt_etc module to actually place the xml file under
632 // <partition>/etc/permissions
633 etcProps := struct {
634 Name *string
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900635 Src *string
Jiyong Parkc678ad32018-04-10 13:07:10 +0900636 Sub_dir *string
637 Soc_specific *bool
638 Device_specific *bool
639 Product_specific *bool
640 }{}
641 etcProps.Name = proptools.StringPtr(module.xmlFileName())
Jiyong Park5a8d1be2018-04-25 22:57:34 +0900642 etcProps.Src = proptools.StringPtr(":" + module.xmlFileName() + "-gen")
Jiyong Parkc678ad32018-04-10 13:07:10 +0900643 etcProps.Sub_dir = proptools.StringPtr("permissions")
644 if module.SocSpecific() {
645 etcProps.Soc_specific = proptools.BoolPtr(true)
646 } else if module.DeviceSpecific() {
647 etcProps.Device_specific = proptools.BoolPtr(true)
648 } else if module.ProductSpecific() {
649 etcProps.Product_specific = proptools.BoolPtr(true)
650 }
651 mctx.CreateModule(android.ModuleFactoryAdaptor(android.PrebuiltEtcFactory), &etcProps)
652}
653
654// to satisfy SdkLibraryDependency interface
655func (module *sdkLibrary) HeaderJars(linkType linkType) android.Paths {
656 // This module is just a wrapper for the stubs.
Sundong Ahn57368eb2018-07-06 11:20:23 +0900657 if linkType == javaSystem {
Jiyong Parkc678ad32018-04-10 13:07:10 +0900658 return module.systemApiStubsPath
Sundong Ahn57368eb2018-07-06 11:20:23 +0900659 } else if linkType == javaPlatform {
660 return module.implLibPath
Jiyong Parkc678ad32018-04-10 13:07:10 +0900661 } else {
662 return module.publicApiStubsPath
663 }
664}
665
Sundong Ahn241cd372018-07-13 16:16:44 +0900666// to satisfy SdkLibraryDependency interface
667func (module *sdkLibrary) ImplementationJars(linkType linkType) android.Paths {
668 // This module is just a wrapper for the stubs.
669 if linkType == javaSystem {
670 return module.systemApiStubsImplPath
671 } else if linkType == javaPlatform {
672 return module.implLibImplPath
673 } else {
674 return module.publicApiStubsImplPath
675 }
676}
677
Jiyong Park82484c02018-04-23 21:41:26 +0900678func javaSdkLibraries(config android.Config) *[]string {
679 return config.Once("javaSdkLibraries", func() interface{} {
680 return &[]string{}
681 }).(*[]string)
682}
683
Jiyong Parkc678ad32018-04-10 13:07:10 +0900684// For a java_sdk_library module, create internal modules for stubs, docs,
685// runtime libs and xml file. If requested, the stubs and docs are created twice
686// once for public API level and once for system API level
687func sdkLibraryMutator(mctx android.TopDownMutatorContext) {
688 if module, ok := mctx.Module().(*sdkLibrary); ok {
Anton Hansson8959e142018-04-25 11:56:13 +0100689 if module.properties.Srcs == nil {
690 mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
691 }
692 if module.properties.Api_packages == nil {
693 mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
694 }
695
Jiyong Parkc678ad32018-04-10 13:07:10 +0900696 // for public API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900697 module.createStubsLibrary(mctx, apiScopePublic)
698 module.createDocs(mctx, apiScopePublic)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900699
700 // for system API stubs
Jiyong Parkdf130542018-04-27 16:29:21 +0900701 module.createStubsLibrary(mctx, apiScopeSystem)
702 module.createDocs(mctx, apiScopeSystem)
703
704 // for test API stubs
705 module.createStubsLibrary(mctx, apiScopeTest)
706 module.createDocs(mctx, apiScopeTest)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900707
708 // for runtime
709 module.createXmlFile(mctx)
710 module.createImplLibrary(mctx)
Jiyong Park82484c02018-04-23 21:41:26 +0900711
712 // record java_sdk_library modules so that they are exported to make
713 javaSdkLibraries := javaSdkLibraries(mctx.Config())
714 javaSdkLibrariesLock.Lock()
715 defer javaSdkLibrariesLock.Unlock()
716 *javaSdkLibraries = append(*javaSdkLibraries, module.BaseModuleName())
Jiyong Parkc678ad32018-04-10 13:07:10 +0900717 }
718}
719
720func sdkLibraryFactory() android.Module {
721 module := &sdkLibrary{}
722 module.AddProperties(&module.properties)
Jiyong Park441a47d2018-05-01 23:33:08 +0900723 module.AddProperties(&module.deviceProperties)
Colin Cross48de9a42018-10-02 13:53:33 -0700724 InitJavaModule(module, android.DeviceSupported)
Jiyong Parkc678ad32018-04-10 13:07:10 +0900725 return module
726}