blob: 86eddb1724bbef14f79b8336b4c081a584c0abb8 [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 (
18 "android/soong/android"
19 "sort"
Jiyong Park58c518b2018-05-12 22:29:12 +090020 "strings"
21
22 "github.com/google/blueprint/proptools"
23)
24
Jiyong Park58c518b2018-05-12 22:29:12 +090025func init() {
Paul Duffina48f7582019-12-19 11:25:19 +000026 RegisterPrebuiltApisBuildComponents(android.InitRegistrationContext)
27}
Jiyong Park58c518b2018-05-12 22:29:12 +090028
Paul Duffina48f7582019-12-19 11:25:19 +000029func RegisterPrebuiltApisBuildComponents(ctx android.RegistrationContext) {
30 ctx.RegisterModuleType("prebuilt_apis", PrebuiltApisFactory)
Jiyong Park58c518b2018-05-12 22:29:12 +090031}
32
Sundong Ahn27eecb92018-06-21 13:47:17 +090033type prebuiltApisProperties struct {
34 // list of api version directories
35 Api_dirs []string
36}
37
Jiyong Park58c518b2018-05-12 22:29:12 +090038type prebuiltApis struct {
39 android.ModuleBase
Sundong Ahn27eecb92018-06-21 13:47:17 +090040 properties prebuiltApisProperties
Jiyong Park58c518b2018-05-12 22:29:12 +090041}
42
Jiyong Park58c518b2018-05-12 22:29:12 +090043func (module *prebuiltApis) GenerateAndroidBuildActions(ctx android.ModuleContext) {
44 // no need to implement
45}
46
Paul Duffind4c03562020-04-09 17:15:44 +010047func parseJarPath(path string) (module string, apiver string, scope string) {
Sundong Ahna01c2a52018-06-07 21:42:16 +090048 elements := strings.Split(path, "/")
49
50 apiver = elements[0]
51 scope = elements[1]
Sundong Ahna01c2a52018-06-07 21:42:16 +090052
53 module = strings.TrimSuffix(elements[2], ".jar")
54 return
55}
56
Paul Duffind4c03562020-04-09 17:15:44 +010057func parseApiFilePath(ctx android.LoadHookContext, path string) (module string, apiver string, scope string) {
Jiyong Park58c518b2018-05-12 22:29:12 +090058 elements := strings.Split(path, "/")
Sundong Ahn054b19a2018-10-19 13:46:09 +090059 apiver = elements[0]
Jiyong Park58c518b2018-05-12 22:29:12 +090060
61 scope = elements[1]
62 if scope != "public" && scope != "system" && scope != "test" {
63 ctx.ModuleErrorf("invalid scope %q found in path: %q", scope, path)
64 return
65 }
66
67 // elements[2] is string literal "api". skipping.
68 module = strings.TrimSuffix(elements[3], ".txt")
69 return
70}
71
Paul Duffind4c03562020-04-09 17:15:44 +010072func createImport(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
Sundong Ahna01c2a52018-06-07 21:42:16 +090073 props := struct {
74 Name *string
75 Jars []string
76 Sdk_version *string
77 Installable *bool
78 }{}
Sundong Ahn27eecb92018-06-21 13:47:17 +090079 props.Name = proptools.StringPtr(mctx.ModuleName() + "_" + scope + "_" + apiver + "_" + module)
Sundong Ahna01c2a52018-06-07 21:42:16 +090080 props.Jars = append(props.Jars, path)
81 // TODO(hansson): change to scope after migration is done.
82 props.Sdk_version = proptools.StringPtr("current")
83 props.Installable = proptools.BoolPtr(false)
84
Colin Cross84dfc3d2019-09-25 11:33:01 -070085 mctx.CreateModule(ImportFactory, &props)
Sundong Ahna01c2a52018-06-07 21:42:16 +090086}
87
Paul Duffind4c03562020-04-09 17:15:44 +010088func createFilegroup(mctx android.LoadHookContext, module string, scope string, apiver string, path string) {
Jiyong Park58c518b2018-05-12 22:29:12 +090089 fgName := module + ".api." + scope + "." + apiver
90 filegroupProps := struct {
91 Name *string
92 Srcs []string
93 }{}
94 filegroupProps.Name = proptools.StringPtr(fgName)
95 filegroupProps.Srcs = []string{path}
Colin Cross84dfc3d2019-09-25 11:33:01 -070096 mctx.CreateModule(android.FileGroupFactory, &filegroupProps)
Jiyong Park58c518b2018-05-12 22:29:12 +090097}
98
Paul Duffind4c03562020-04-09 17:15:44 +010099func getPrebuiltFiles(mctx android.LoadHookContext, name string) []string {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900100 mydir := mctx.ModuleDir() + "/"
Sundong Ahn27eecb92018-06-21 13:47:17 +0900101 var files []string
102 for _, apiver := range mctx.Module().(*prebuiltApis).properties.Api_dirs {
103 for _, scope := range []string{"public", "system", "test", "core"} {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900104 vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil)
Sundong Ahn27eecb92018-06-21 13:47:17 +0900105 if err != nil {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900106 mctx.ModuleErrorf("failed to glob %s files under %q: %s", name, mydir+apiver+"/"+scope, err)
Sundong Ahn27eecb92018-06-21 13:47:17 +0900107 }
108 files = append(files, vfiles...)
109 }
Sundong Ahna01c2a52018-06-07 21:42:16 +0900110 }
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900111 return files
112}
113
Paul Duffind4c03562020-04-09 17:15:44 +0100114func prebuiltSdkStubs(mctx android.LoadHookContext) {
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900115 mydir := mctx.ModuleDir() + "/"
116 // <apiver>/<scope>/<module>.jar
117 files := getPrebuiltFiles(mctx, "*.jar")
Sundong Ahna01c2a52018-06-07 21:42:16 +0900118
119 for _, f := range files {
120 // create a Import module for each jar file
121 localPath := strings.TrimPrefix(f, mydir)
Paul Duffind4c03562020-04-09 17:15:44 +0100122 module, apiver, scope := parseJarPath(localPath)
Sundong Ahn27eecb92018-06-21 13:47:17 +0900123 createImport(mctx, module, scope, apiver, localPath)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900124 }
125}
126
Paul Duffind4c03562020-04-09 17:15:44 +0100127func prebuiltApiFiles(mctx android.LoadHookContext) {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900128 mydir := mctx.ModuleDir() + "/"
129 // <apiver>/<scope>/api/<module>.txt
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900130 files := getPrebuiltFiles(mctx, "api/*.txt")
131
Sundong Ahna01c2a52018-06-07 21:42:16 +0900132 if len(files) == 0 {
133 mctx.ModuleErrorf("no api file found under %q", mydir)
134 }
135
136 // construct a map to find out the latest api file path
137 // for each (<module>, <scope>) pair.
138 type latestApiInfo struct {
139 module string
140 scope string
Sundong Ahn054b19a2018-10-19 13:46:09 +0900141 apiver string
Sundong Ahna01c2a52018-06-07 21:42:16 +0900142 path string
143 }
144 m := make(map[string]latestApiInfo)
145
146 for _, f := range files {
147 // create a filegroup for each api txt file
148 localPath := strings.TrimPrefix(f, mydir)
149 module, apiver, scope := parseApiFilePath(mctx, localPath)
Sundong Ahn054b19a2018-10-19 13:46:09 +0900150 createFilegroup(mctx, module, scope, apiver, localPath)
Sundong Ahna01c2a52018-06-07 21:42:16 +0900151
152 // find the latest apiver
153 key := module + "." + scope
154 info, ok := m[key]
155 if !ok {
156 m[key] = latestApiInfo{module, scope, apiver, localPath}
Sundong Ahn054b19a2018-10-19 13:46:09 +0900157 } else if len(apiver) > len(info.apiver) || (len(apiver) == len(info.apiver) &&
158 strings.Compare(apiver, info.apiver) > 0) {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900159 info.apiver = apiver
160 info.path = localPath
Sundong Ahn8faab8a2019-02-14 11:49:24 +0900161 m[key] = info
Sundong Ahna01c2a52018-06-07 21:42:16 +0900162 }
163 }
164 // create filegroups for the latest version of (<module>, <scope>) pairs
165 // sort the keys in order to make build.ninja stable
166 keys := make([]string, 0, len(m))
167 for k := range m {
168 keys = append(keys, k)
169 }
170 sort.Strings(keys)
171 for _, k := range keys {
172 info := m[k]
173 createFilegroup(mctx, info.module, info.scope, "latest", info.path)
174 }
175}
176
Paul Duffind4c03562020-04-09 17:15:44 +0100177func createPrebuiltApiModules(mctx android.LoadHookContext) {
Jiyong Park58c518b2018-05-12 22:29:12 +0900178 if _, ok := mctx.Module().(*prebuiltApis); ok {
Sundong Ahna01c2a52018-06-07 21:42:16 +0900179 prebuiltApiFiles(mctx)
180 prebuiltSdkStubs(mctx)
Jiyong Park58c518b2018-05-12 22:29:12 +0900181 }
182}
183
Jaewoong Jung5fb5b2a2019-03-21 10:48:25 -0700184// prebuilt_apis is a meta-module that generates filegroup modules for all
185// API txt files found under the directory where the Android.bp is located.
186// Specifically, an API file located at ./<ver>/<scope>/api/<module>.txt
187// generates a filegroup module named <module>-api.<scope>.<ver>.
188//
189// It also creates <module>-api.<scope>.latest for the latest <ver>.
Paul Duffind4c03562020-04-09 17:15:44 +0100190//
191// Similarly, it generates a java_import for all API .jar files found under the
192// directory where the Android.bp is located. Specifically, an API file located
193// at ./<ver>/<scope>/api/<module>.jar generates a java_import module named
194// <prebuilt-api-module>.<scope>.<ver>.<module>.
Inseob Kimc0907f12019-02-08 21:00:45 +0900195func PrebuiltApisFactory() android.Module {
Jiyong Park58c518b2018-05-12 22:29:12 +0900196 module := &prebuiltApis{}
Sundong Ahn27eecb92018-06-21 13:47:17 +0900197 module.AddProperties(&module.properties)
Jiyong Park58c518b2018-05-12 22:29:12 +0900198 android.InitAndroidModule(module)
Paul Duffind4c03562020-04-09 17:15:44 +0100199 android.AddLoadHook(module, createPrebuiltApiModules)
Jiyong Park58c518b2018-05-12 22:29:12 +0900200 return module
201}