blob: 0ffbaaa4094156c6eb5dc20c1805fbbac427cebb [file] [log] [blame]
Jiyong Park58c518b2018-05-12 22:29:12 +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 (
Anton Hansson370fd0b2021-01-22 15:05:04 +000018 "strconv"
Jiyong Park58c518b2018-05-12 22:29:12 +090019 "strings"
20
21 "github.com/google/blueprint/proptools"
Colin Cross17dec172020-05-14 18:05:32 -070022
23 "android/soong/android"
Jiyong Park58c518b2018-05-12 22:29:12 +090024)
25
Jiyong Park58c518b2018-05-12 22:29:12 +090026func init() {
Paul Duffina48f7582019-12-19 11:25:19 +000027 RegisterPrebuiltApisBuildComponents(android.InitRegistrationContext)
28}
Jiyong Park58c518b2018-05-12 22:29:12 +090029
Paul Duffina48f7582019-12-19 11:25:19 +000030func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) {
31 ctx.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
Jiyong Park58c518b2018-05-12 22:29:12 +090032}
33
Sundong Ahn27eecb92018-06-21 13:47:17 +090034type prebuiltApisProperties struct {
35 // list of api version directories
36 Api_dirs []string
Liz Kammer2d2fd852020-08-12 14:42:30 -070037
38 // The sdk_version of java_import modules generated based on jar files.
39 // Defaults to "current"
40 Imports_sdk_version *string
Liz Kammer4e7f2602020-09-02 08:37:49 -070041
42 // If set to true, compile dex for java_import modules. Defaults to false.
43 Imports_compile_dex *bool
Sundong Ahn27eecb92018-06-21 13:47:17 +090044}
45
Jiyong Park58c518b2018-05-12 22:29:12 +090046type prebuiltApis struct {
47 android.ModuleBase
Sundong Ahn27eecb92018-06-21 13:47:17 +090048 properties prebuiltApisProperties
Jiyong Park58c518b2018-05-12 22:29:12 +090049}
50
Jiyong Park58c518b2018-05-12 22:29:12 +090051func (module *prebuiltApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
52 // no need to implement
53}
54
Paul Duffind4c03562020-04-09 17:15:44 +010055func parseJarPath(path string) (module string, apiver string, scope string) {
Sundong Ahna01c2a52018-06-07 21:42:16 +090056 elements := strings.Split(path, "/")
57
58 apiver = elements[0]
59 scope = elements[1]
Sundong Ahna01c2a52018-06-07 21:42:16 +090060
61 module = strings.TrimSuffix(elements[2], ".jar")
62 return
63}
64
Paul Duffind4c03562020-04-09 17:15:44 +010065func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, apiver string, scope string) {
Jiyong Park58c518b2018-05-12 22:29:12 +090066 elements := strings.Split(path, "/")
Sundong Ahn054b19a2018-10-19 13:46:09 +090067 apiver = elements[0]
Jiyong Park58c518b2018-05-12 22:29:12 +090068
69 scope = elements[1]
Anton Hansson8d239692020-05-01 18:37:15 +010070 if scope != "public" && scope != "system" && scope != "test" && scope != "module-lib" && scope != "system-server" {
Jiyong Park58c518b2018-05-12 22:29:12 +090071 ctx.ModuleErrorf("invalid scope %q found in path: %q", scope, path)
72 return
73 }
74
75 // elements[2] is string literal "api". skipping.
76 module = strings.TrimSuffix(elements[3], ".txt")
77 return
78}
79
Colin Cross17dec172020-05-14 18:05:32 -070080func prebuiltApiModuleName(mctx android.LoadHookContext, module string, scope string, apiver string) string {
81 return mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module
82}
83
Liz Kammer4e7f2602020-09-02 08:37:49 -070084func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdkVersion string, compileDex bool) {
Sundong Ahna01c2a52018-06-07 21:42:16 +090085 props := struct {
86 Name *string
87 Jars []string
88 Sdk_version *string
89 Installable *bool
Liz Kammer4e7f2602020-09-02 08:37:49 -070090 Compile_dex *bool
Sundong Ahna01c2a52018-06-07 21:42:16 +090091 }{}
Colin Cross17dec172020-05-14 18:05:32 -070092 props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, apiver))
Sundong Ahna01c2a52018-06-07 21:42:16 +090093 props.Jars = append(props.Jars, path)
Liz Kammer4e7f2602020-09-02 08:37:49 -070094 props.Sdk_version = proptools.StringPtr(sdkVersion)
Sundong Ahna01c2a52018-06-07 21:42:16 +090095 props.Installable = proptools.BoolPtr(false)
Liz Kammer4e7f2602020-09-02 08:37:49 -070096 props.Compile_dex = proptools.BoolPtr(compileDex)
Sundong Ahna01c2a52018-06-07 21:42:16 +090097
Colin Cross84dfc3d2019-09-25 11:33:01 -070098 mctx.CreateModule(ImportFactory, &props)
Sundong Ahna01c2a52018-06-07 21:42:16 +090099}
100
Paul Duffind4c03562020-04-09 17:15:44 +0100101func createFilegroup(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
Jiyong Park58c518b2018-05-12 22:29:12 +0900102 fgName := module + ".api." + scope + "." + apiver
103 filegroupProps := struct {
104 Name *string
105 Srcs []string
106 }{}
107 filegroupProps.Name = proptools.StringPtr(fgName)
108 filegroupProps.Srcs = []string{path}
Colin Cross84dfc3d2019-09-25 11:33:01 -0700109 mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
Jiyong Park58c518b2018-05-12 22:29:12 +0900110}
111
Liz Kammer2d2fd852020-08-12 14:42:30 -0700112func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900113 mydir := mctx.ModuleDir() + "/"
Sundong Ahn27eecb92018-06-21 13:47:17 +0900114 var files []string
Liz Kammer2d2fd852020-08-12 14:42:30 -0700115 for _, apiver := range p.properties.Api_dirs {
Anton Hansson8d239692020-05-01 18:37:15 +0100116 for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900117 vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil)
Sundong Ahn27eecb92018-06-21 13:47:17 +0900118 if err != nil {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900119 mctx.ModuleErrorf("failed to glob %s files under %q: %s", name, mydir+apiver+"/"+scope, err)
Sundong Ahn27eecb92018-06-21 13:47:17 +0900120 }
121 files = append(files, vfiles...)
122 }
Sundong Ahna01c2a52018-06-07 21:42:16 +0900123 }
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900124 return files
125}
126
Liz Kammer2d2fd852020-08-12 14:42:30 -0700127func prebuiltSdkStubs(mctx android.LoadHookContext, p *prebuiltApis) {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900128 mydir := mctx.ModuleDir() + "/"
129 // <apiver>/<scope>/<module>.jar
Liz Kammer2d2fd852020-08-12 14:42:30 -0700130 files := getPrebuiltFiles(mctx, p, "*.jar")
131
Liz Kammer4e7f2602020-09-02 08:37:49 -0700132 sdkVersion := proptools.StringDefault(p.properties.Imports_sdk_version, "current")
133 compileDex := proptools.BoolDefault(p.properties.Imports_compile_dex, false)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900134
135 for _, f := range files {
136 // create a Import module for each jar file
137 localPath := strings.TrimPrefix(f, mydir)
Paul Duffind4c03562020-04-09 17:15:44 +0100138 module, apiver, scope := parseJarPath(localPath)
Liz Kammer4e7f2602020-09-02 08:37:49 -0700139 createImport(mctx, module, scope, apiver, localPath, sdkVersion, compileDex)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900140 }
141}
142
Colin Cross17dec172020-05-14 18:05:32 -0700143func createSystemModules(mctx android.LoadHookContext, apiver string) {
144 props := struct {
145 Name *string
146 Libs []string
147 }{}
148 props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver))
149 props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver))
150
151 mctx.CreateModule(SystemModulesFactory, &props)
152}
153
Liz Kammer2d2fd852020-08-12 14:42:30 -0700154func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) {
155 for _, apiver := range p.properties.Api_dirs {
Colin Cross17dec172020-05-14 18:05:32 -0700156 jar := android.ExistentPathForSource(mctx,
157 mctx.ModuleDir(), apiver, "public", "core-for-system-modules.jar")
158 if jar.Valid() {
159 createSystemModules(mctx, apiver)
160 }
161 }
162}
163
Liz Kammer2d2fd852020-08-12 14:42:30 -0700164func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900165 mydir := mctx.ModuleDir() + "/"
166 // <apiver>/<scope>/api/<module>.txt
Liz Kammer2d2fd852020-08-12 14:42:30 -0700167 files := getPrebuiltFiles(mctx, p, "api/*.txt")
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900168
Sundong Ahna01c2a52018-06-07 21:42:16 +0900169 if len(files) == 0 {
170 mctx.ModuleErrorf("no api file found under %q", mydir)
171 }
172
173 // construct a map to find out the latest api file path
174 // for each (<module>, <scope>) pair.
175 type latestApiInfo struct {
Anton Hansson370fd0b2021-01-22 15:05:04 +0000176 module string
177 scope string
178 version int
179 path string
Sundong Ahna01c2a52018-06-07 21:42:16 +0900180 }
Sundong Ahna01c2a52018-06-07 21:42:16 +0900181
Anton Hansson370fd0b2021-01-22 15:05:04 +0000182 // Create filegroups for all (<module>, <scope, <version>) triplets,
183 // and a "latest" filegroup variant for each (<module>, <scope>) pair
184 m := make(map[string]latestApiInfo)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900185 for _, f := range files {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900186 localPath := strings.TrimPrefix(f, mydir)
187 module, apiver, scope := parseApiFilePath(mctx, localPath)
Sundong Ahn054b19a2018-10-19 13:46:09 +0900188 createFilegroup(mctx, module, scope, apiver, localPath)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900189
Anton Hansson370fd0b2021-01-22 15:05:04 +0000190 version, err := strconv.Atoi(apiver)
191 if err != nil {
192 mctx.ModuleErrorf("Found finalized API files in non-numeric dir %v", apiver)
193 return
194 }
195
Sundong Ahna01c2a52018-06-07 21:42:16 +0900196 key := module + "." + scope
197 info, ok := m[key]
198 if !ok {
Anton Hansson370fd0b2021-01-22 15:05:04 +0000199 m[key] = latestApiInfo{module, scope, version, localPath}
200 } else if version > info.version {
201 info.version = version
Sundong Ahna01c2a52018-06-07 21:42:16 +0900202 info.path = localPath
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900203 m[key] = info
Sundong Ahna01c2a52018-06-07 21:42:16 +0900204 }
205 }
Anton Hansson370fd0b2021-01-22 15:05:04 +0000206 // Sort the keys in order to make build.ninja stable
207 for _, k := range android.SortedStringKeys(m) {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900208 info := m[k]
209 createFilegroup(mctx, info.module, info.scope, "latest", info.path)
210 }
211}
212
Paul Duffind4c03562020-04-09 17:15:44 +0100213func createPrebuiltApiModules(mctx android.LoadHookContext) {
Liz Kammer2d2fd852020-08-12 14:42:30 -0700214 if p, ok := mctx.Module().(*prebuiltApis); ok {
215 prebuiltApiFiles(mctx, p)
216 prebuiltSdkStubs(mctx, p)
217 prebuiltSdkSystemModules(mctx, p)
Jiyong Park58c518b2018-05-12 22:29:12 +0900218 }
219}
220
Jaewoong Jung5fb5b2a2019-03-21 10:48:25 -0700221// prebuilt_apis is a meta-module that generates filegroup modules for all
222// API txt files found under the directory where the Android.bp is located.
223// Specifically, an API file located at ./<ver>/<scope>/api/<module>.txt
224// generates a filegroup module named <module>-api.<scope>.<ver>.
225//
226// It also creates <module>-api.<scope>.latest for the latest <ver>.
Paul Duffind4c03562020-04-09 17:15:44 +0100227//
228// Similarly, it generates a java_import for all API .jar files found under the
229// directory where the Android.bp is located. Specifically, an API file located
230// at ./<ver>/<scope>/api/<module>.jar generates a java_import module named
Colin Cross17dec172020-05-14 18:05:32 -0700231// <prebuilt-api-module>_<scope>_<ver>_<module>, and for SDK versions >= 30
232// a java_system_modules module named
233// <prebuilt-api-module>_public_<ver>_system_modules
Inseob Kimc0907f12019-02-08 21:00:45 +0900234func PrebuiltApisFactory() android.Module {
Jiyong Park58c518b2018-05-12 22:29:12 +0900235 module := &prebuiltApis{}
Sundong Ahn27eecb92018-06-21 13:47:17 +0900236 module.AddProperties(&module.properties)
Jiyong Park58c518b2018-05-12 22:29:12 +0900237 android.InitAndroidModule(module)
Paul Duffind4c03562020-04-09 17:15:44 +0100238 android.AddLoadHook(module, createPrebuiltApiModules)
Jiyong Park58c518b2018-05-12 22:29:12 +0900239 return module
240}