blob: c7669bd9dc38cd60730caa3b9ccefbfe2026c7f3 [file] [log] [blame]
Inseob Kimc0907f12019-02-08 21:00:45 +09001// Copyright (C) 2019 The Android Open Source Project
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 sysprop
16
17import (
Inseob Kim42882742019-07-30 17:55:33 +090018 "fmt"
19 "io"
20 "path"
Colin Crossf8b860a2019-04-16 14:43:28 -070021
Inseob Kimc0907f12019-02-08 21:00:45 +090022 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
Inseob Kim42882742019-07-30 17:55:33 +090024
25 "android/soong/android"
26 "android/soong/cc"
27 "android/soong/java"
Inseob Kimc0907f12019-02-08 21:00:45 +090028)
29
30type dependencyTag struct {
31 blueprint.BaseDependencyTag
32 name string
33}
34
35type syspropLibrary struct {
Inseob Kim42882742019-07-30 17:55:33 +090036 android.ModuleBase
Inseob Kimc0907f12019-02-08 21:00:45 +090037
Inseob Kim42882742019-07-30 17:55:33 +090038 properties syspropLibraryProperties
39
40 checkApiFileTimeStamp android.WritablePath
41 latestApiFile android.Path
42 currentApiFile android.Path
43 dumpedApiFile android.WritablePath
Inseob Kimc0907f12019-02-08 21:00:45 +090044}
45
46type syspropLibraryProperties struct {
47 // Determine who owns this sysprop library. Possible values are
48 // "Platform", "Vendor", or "Odm"
49 Property_owner string
Inseob Kimf63c2fb2019-03-05 14:22:30 +090050
51 // list of package names that will be documented and publicized as API
52 Api_packages []string
Inseob Kimc0907f12019-02-08 21:00:45 +090053
Inseob Kim42882742019-07-30 17:55:33 +090054 // If set to true, allow this module to be dexed and installed on devices.
55 Installable *bool
56
57 // Make this module available when building for recovery
Jiyong Park854a9442019-02-26 10:27:13 +090058 Recovery_available *bool
Inseob Kim42882742019-07-30 17:55:33 +090059
60 // Make this module available when building for vendor
61 Vendor_available *bool
62
63 // list of .sysprop files which defines the properties.
64 Srcs []string `android:"path"`
Inseob Kimc0907f12019-02-08 21:00:45 +090065}
66
67var (
Inseob Kim42882742019-07-30 17:55:33 +090068 pctx = android.NewPackageContext("android/soong/sysprop")
Inseob Kimc0907f12019-02-08 21:00:45 +090069 syspropCcTag = dependencyTag{name: "syspropCc"}
70)
71
72func init() {
73 android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
74}
75
Inseob Kim42882742019-07-30 17:55:33 +090076func (m *syspropLibrary) Name() string {
77 return m.BaseModuleName() + "_sysprop_library"
Inseob Kimc0907f12019-02-08 21:00:45 +090078}
79
Inseob Kim42882742019-07-30 17:55:33 +090080func (m *syspropLibrary) CcModuleName() string {
81 return "lib" + m.BaseModuleName()
82}
83
84func (m *syspropLibrary) BaseModuleName() string {
85 return m.ModuleBase.Name()
86}
87
88func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
89 m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-current.txt")
90 m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-latest.txt")
91
92 // dump API rule
93 rule := android.NewRuleBuilder()
94 m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt")
95 rule.Command().
96 BuiltTool(ctx, "sysprop_api_dump").
97 Output(m.dumpedApiFile).
98 Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
99 rule.Build(pctx, ctx, m.BaseModuleName()+"_api_dump", m.BaseModuleName()+" api dump")
100
101 // check API rule
102 rule = android.NewRuleBuilder()
103
104 // 1. current.txt <-> api_dump.txt
105 msg := fmt.Sprintf(`\n******************************\n`+
106 `API of sysprop_library %s doesn't match with current.txt\n`+
107 `Please update current.txt by:\n`+
108 `rm -rf %q && cp -f %q %q\n`+
109 `******************************\n`, m.BaseModuleName(),
110 m.currentApiFile.String(), m.dumpedApiFile.String(), m.currentApiFile.String())
111
112 rule.Command().
113 Text("( cmp").Flag("-s").
114 Input(m.dumpedApiFile).
115 Input(m.currentApiFile).
116 Text("|| ( echo").Flag("-e").
117 Flag(`"` + msg + `"`).
118 Text("; exit 38) )")
119
120 // 2. current.txt <-> latest.txt
121 msg = fmt.Sprintf(`\n******************************\n`+
122 `API of sysprop_library %s doesn't match with latest version\n`+
123 `Please fix the breakage and rebuild.\n`+
124 `******************************\n`, m.BaseModuleName())
125
126 rule.Command().
127 Text("( ").
128 BuiltTool(ctx, "sysprop_api_checker").
129 Input(m.latestApiFile).
130 Input(m.currentApiFile).
131 Text(" || ( echo").Flag("-e").
132 Flag(`"` + msg + `"`).
133 Text("; exit 38) )")
134
135 m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp")
136
137 rule.Command().
138 Text("touch").
139 Output(m.checkApiFileTimeStamp)
140
141 rule.Build(pctx, ctx, m.BaseModuleName()+"_check_api", m.BaseModuleName()+" check api")
142}
143
144func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
145 return android.AndroidMkData{
146 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
147 // sysprop_library module itself is defined as a FAKE module to perform API check.
148 // Actual implementation libraries are created on LoadHookMutator
149 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
150 fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name())
151 fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
152 fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
153 fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
154 fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
155 fmt.Fprintf(w, "\ttouch $@\n\n")
156 fmt.Fprintf(w, ".PHONY: %s-check-api\n\n", name)
157
158 // check API rule
159 fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
160
161 // "make {sysprop_library}" should also build the C++ library
162 fmt.Fprintf(w, "%s: %s\n\n", name, m.CcModuleName())
163 }}
164}
165
166// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
167// Both Java and C++ modules can link against sysprop_library, and API stability check
168// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
169// is performed.
Inseob Kimc0907f12019-02-08 21:00:45 +0900170func syspropLibraryFactory() android.Module {
171 m := &syspropLibrary{}
172
173 m.AddProperties(
Inseob Kim42882742019-07-30 17:55:33 +0900174 &m.properties,
Inseob Kimc0907f12019-02-08 21:00:45 +0900175 )
Inseob Kim42882742019-07-30 17:55:33 +0900176 android.InitAndroidModule(m)
Inseob Kimc0907f12019-02-08 21:00:45 +0900177 android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
Inseob Kimc0907f12019-02-08 21:00:45 +0900178 return m
179}
180
181func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
Inseob Kim42882742019-07-30 17:55:33 +0900182 if len(m.properties.Srcs) == 0 {
Inseob Kim6e93ac92019-03-21 17:43:49 +0900183 ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
184 }
185
Inseob Kim42882742019-07-30 17:55:33 +0900186 missing_api := false
187
188 for _, txt := range []string{"-current.txt", "-latest.txt"} {
189 path := path.Join(ctx.ModuleDir(), "api", m.BaseModuleName()+txt)
190 file := android.ExistentPathForSource(ctx, path)
191 if !file.Valid() {
192 ctx.ModuleErrorf("API file %#v doesn't exist", path)
193 missing_api = true
194 }
195 }
196
197 if missing_api {
198 script := "build/soong/scripts/gen-sysprop-api-files.sh"
199 p := android.ExistentPathForSource(ctx, script)
200
201 if !p.Valid() {
202 panic(fmt.Sprintf("script file %s doesn't exist", script))
203 }
204
205 ctx.ModuleErrorf("One or more api files are missing. "+
206 "You can create them by:\n"+
207 "%s %q %q", script, ctx.ModuleDir(), m.BaseModuleName())
208 return
Inseob Kimc0907f12019-02-08 21:00:45 +0900209 }
210
211 socSpecific := ctx.SocSpecific()
212 deviceSpecific := ctx.DeviceSpecific()
213 productSpecific := ctx.ProductSpecific()
214
Inseob Kim42882742019-07-30 17:55:33 +0900215 owner := m.properties.Property_owner
216 stub := "sysprop-library-stub-"
Inseob Kimc0907f12019-02-08 21:00:45 +0900217
218 switch owner {
219 case "Platform":
220 // Every partition can access platform-defined properties
Inseob Kim42882742019-07-30 17:55:33 +0900221 stub += "platform"
Inseob Kimc0907f12019-02-08 21:00:45 +0900222 case "Vendor":
223 // System can't access vendor's properties
224 if !socSpecific && !deviceSpecific && !productSpecific {
225 ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
226 "System can't access sysprop_library owned by Vendor")
227 }
Inseob Kim42882742019-07-30 17:55:33 +0900228 stub += "vendor"
Inseob Kimc0907f12019-02-08 21:00:45 +0900229 case "Odm":
230 // Only vendor can access Odm-defined properties
231 if !socSpecific && !deviceSpecific {
232 ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
233 "Odm-defined properties should be accessed only in Vendor or Odm")
234 }
Inseob Kim42882742019-07-30 17:55:33 +0900235 stub += "vendor"
Inseob Kimc0907f12019-02-08 21:00:45 +0900236 default:
237 ctx.PropertyErrorf("property_owner",
238 "Unknown value %s: must be one of Platform, Vendor or Odm", owner)
239 }
240
241 ccProps := struct {
242 Name *string
Inseob Kim42882742019-07-30 17:55:33 +0900243 Srcs []string
Inseob Kimc0907f12019-02-08 21:00:45 +0900244 Soc_specific *bool
245 Device_specific *bool
246 Product_specific *bool
247 Sysprop struct {
248 Platform *bool
249 }
Inseob Kim42882742019-07-30 17:55:33 +0900250 Header_libs []string
251 Shared_libs []string
252 Required []string
253 Recovery *bool
254 Recovery_available *bool
255 Vendor_available *bool
Inseob Kimc0907f12019-02-08 21:00:45 +0900256 }{}
257
258 ccProps.Name = proptools.StringPtr(m.CcModuleName())
Inseob Kim42882742019-07-30 17:55:33 +0900259 ccProps.Srcs = m.properties.Srcs
Inseob Kimc0907f12019-02-08 21:00:45 +0900260 ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
261 ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
262 ccProps.Product_specific = proptools.BoolPtr(productSpecific)
263 ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
Inseob Kimda63a492019-06-10 23:03:16 +0900264 ccProps.Header_libs = []string{"libbase_headers"}
265 ccProps.Shared_libs = []string{"liblog"}
Inseob Kimc0907f12019-02-08 21:00:45 +0900266
Inseob Kim42882742019-07-30 17:55:33 +0900267 // add sysprop_library module to perform check API
268 ccProps.Required = []string{m.Name()}
269 ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
270 ccProps.Recovery_available = m.properties.Recovery_available
271 ccProps.Vendor_available = m.properties.Vendor_available
272
273 ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProps)
274
275 javaProps := struct {
276 Name *string
277 Srcs []string
278 Soc_specific *bool
279 Device_specific *bool
280 Product_specific *bool
281 Sysprop struct {
282 Platform *bool
283 }
284 Required []string
285 Sdk_version *string
286 Installable *bool
287 Libs []string
288 }{}
289
290 javaProps.Name = proptools.StringPtr(m.BaseModuleName())
291 javaProps.Srcs = m.properties.Srcs
292 javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
293 javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
294 javaProps.Product_specific = proptools.BoolPtr(productSpecific)
295 javaProps.Installable = m.properties.Installable
296
297 // add sysprop_library module to perform check API
298 javaProps.Required = []string{m.Name()}
299 javaProps.Sdk_version = proptools.StringPtr("core_current")
300 javaProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
301 javaProps.Libs = []string{stub}
302
303 ctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProps)
Inseob Kimc0907f12019-02-08 21:00:45 +0900304}