blob: 5eb7fa9ac128cedc4a3392773a6be2f9e5afb9a3 [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
Inseob Kim988f53c2019-09-16 15:59:01 +090035type syspropGenProperties struct {
36 Srcs []string `android:"path"`
37 Scope string
38}
39
40type syspropJavaGenRule struct {
41 android.ModuleBase
42
43 properties syspropGenProperties
44
45 genSrcjars android.Paths
46}
47
48var _ android.OutputFileProducer = (*syspropJavaGenRule)(nil)
49
50var (
51 syspropJava = pctx.AndroidStaticRule("syspropJava",
52 blueprint.RuleParams{
53 Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
54 `$syspropJavaCmd --scope $scope --java-output-dir $out.tmp $in && ` +
55 `$soongZipCmd -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
56 CommandDeps: []string{
57 "$syspropJavaCmd",
58 "$soongZipCmd",
59 },
60 }, "scope")
61)
62
63func init() {
64 pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
65 pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
66
67 android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
68 ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
69 })
70}
71
72func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
73 var checkApiFileTimeStamp android.WritablePath
74
75 ctx.VisitDirectDeps(func(dep android.Module) {
76 if m, ok := dep.(*syspropLibrary); ok {
77 checkApiFileTimeStamp = m.checkApiFileTimeStamp
78 }
79 })
80
81 for _, syspropFile := range android.PathsForModuleSrc(ctx, g.properties.Srcs) {
82 srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
83
84 ctx.Build(pctx, android.BuildParams{
85 Rule: syspropJava,
86 Description: "sysprop_java " + syspropFile.Rel(),
87 Output: srcJarFile,
88 Input: syspropFile,
89 Implicit: checkApiFileTimeStamp,
90 Args: map[string]string{
91 "scope": g.properties.Scope,
92 },
93 })
94
95 g.genSrcjars = append(g.genSrcjars, srcJarFile)
96 }
97}
98
99func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) {
100 switch tag {
101 case "":
102 return g.genSrcjars, nil
103 default:
104 return nil, fmt.Errorf("unsupported module reference tag %q", tag)
105 }
106}
107
108func syspropJavaGenFactory() android.Module {
109 g := &syspropJavaGenRule{}
110 g.AddProperties(&g.properties)
111 android.InitAndroidModule(g)
112 return g
113}
114
Inseob Kimc0907f12019-02-08 21:00:45 +0900115type syspropLibrary struct {
Inseob Kim42882742019-07-30 17:55:33 +0900116 android.ModuleBase
Inseob Kimc0907f12019-02-08 21:00:45 +0900117
Inseob Kim42882742019-07-30 17:55:33 +0900118 properties syspropLibraryProperties
119
120 checkApiFileTimeStamp android.WritablePath
121 latestApiFile android.Path
122 currentApiFile android.Path
123 dumpedApiFile android.WritablePath
Inseob Kimc0907f12019-02-08 21:00:45 +0900124}
125
126type syspropLibraryProperties struct {
127 // Determine who owns this sysprop library. Possible values are
128 // "Platform", "Vendor", or "Odm"
129 Property_owner string
Inseob Kimf63c2fb2019-03-05 14:22:30 +0900130
131 // list of package names that will be documented and publicized as API
132 Api_packages []string
Inseob Kimc0907f12019-02-08 21:00:45 +0900133
Inseob Kim42882742019-07-30 17:55:33 +0900134 // If set to true, allow this module to be dexed and installed on devices.
135 Installable *bool
136
137 // Make this module available when building for recovery
Jiyong Park854a9442019-02-26 10:27:13 +0900138 Recovery_available *bool
Inseob Kim42882742019-07-30 17:55:33 +0900139
140 // Make this module available when building for vendor
141 Vendor_available *bool
142
143 // list of .sysprop files which defines the properties.
144 Srcs []string `android:"path"`
Inseob Kimc0907f12019-02-08 21:00:45 +0900145}
146
147var (
Inseob Kim42882742019-07-30 17:55:33 +0900148 pctx = android.NewPackageContext("android/soong/sysprop")
Inseob Kimc0907f12019-02-08 21:00:45 +0900149 syspropCcTag = dependencyTag{name: "syspropCc"}
150)
151
152func init() {
153 android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
154}
155
Inseob Kim42882742019-07-30 17:55:33 +0900156func (m *syspropLibrary) Name() string {
157 return m.BaseModuleName() + "_sysprop_library"
Inseob Kimc0907f12019-02-08 21:00:45 +0900158}
159
Inseob Kim42882742019-07-30 17:55:33 +0900160func (m *syspropLibrary) CcModuleName() string {
161 return "lib" + m.BaseModuleName()
162}
163
Inseob Kim988f53c2019-09-16 15:59:01 +0900164func (m *syspropLibrary) javaGenModuleName() string {
165 return m.BaseModuleName() + "_java_gen"
166}
167
Inseob Kim42882742019-07-30 17:55:33 +0900168func (m *syspropLibrary) BaseModuleName() string {
169 return m.ModuleBase.Name()
170}
171
172func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
Inseob Kim988f53c2019-09-16 15:59:01 +0900173 baseModuleName := m.BaseModuleName()
174
175 for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) {
176 if syspropFile.Ext() != ".sysprop" {
177 ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
178 }
179 }
180
181 if ctx.Failed() {
182 return
183 }
184
185 m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-current.txt")
186 m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", baseModuleName+"-latest.txt")
Inseob Kim42882742019-07-30 17:55:33 +0900187
188 // dump API rule
189 rule := android.NewRuleBuilder()
190 m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt")
191 rule.Command().
192 BuiltTool(ctx, "sysprop_api_dump").
193 Output(m.dumpedApiFile).
194 Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
Inseob Kim988f53c2019-09-16 15:59:01 +0900195 rule.Build(pctx, ctx, baseModuleName+"_api_dump", baseModuleName+" api dump")
Inseob Kim42882742019-07-30 17:55:33 +0900196
197 // check API rule
198 rule = android.NewRuleBuilder()
199
200 // 1. current.txt <-> api_dump.txt
201 msg := fmt.Sprintf(`\n******************************\n`+
202 `API of sysprop_library %s doesn't match with current.txt\n`+
203 `Please update current.txt by:\n`+
Inseob Kim988f53c2019-09-16 15:59:01 +0900204 `m %s-dump-api && rm -rf %q && cp -f %q %q\n`+
205 `******************************\n`, baseModuleName, baseModuleName,
Inseob Kim42882742019-07-30 17:55:33 +0900206 m.currentApiFile.String(), m.dumpedApiFile.String(), m.currentApiFile.String())
207
208 rule.Command().
209 Text("( cmp").Flag("-s").
210 Input(m.dumpedApiFile).
211 Input(m.currentApiFile).
212 Text("|| ( echo").Flag("-e").
213 Flag(`"` + msg + `"`).
214 Text("; exit 38) )")
215
216 // 2. current.txt <-> latest.txt
217 msg = fmt.Sprintf(`\n******************************\n`+
218 `API of sysprop_library %s doesn't match with latest version\n`+
219 `Please fix the breakage and rebuild.\n`+
Inseob Kim988f53c2019-09-16 15:59:01 +0900220 `******************************\n`, baseModuleName)
Inseob Kim42882742019-07-30 17:55:33 +0900221
222 rule.Command().
223 Text("( ").
224 BuiltTool(ctx, "sysprop_api_checker").
225 Input(m.latestApiFile).
226 Input(m.currentApiFile).
227 Text(" || ( echo").Flag("-e").
228 Flag(`"` + msg + `"`).
229 Text("; exit 38) )")
230
231 m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp")
232
233 rule.Command().
234 Text("touch").
235 Output(m.checkApiFileTimeStamp)
236
Inseob Kim988f53c2019-09-16 15:59:01 +0900237 rule.Build(pctx, ctx, baseModuleName+"_check_api", baseModuleName+" check api")
Inseob Kim42882742019-07-30 17:55:33 +0900238}
239
240func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
241 return android.AndroidMkData{
242 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
243 // sysprop_library module itself is defined as a FAKE module to perform API check.
244 // Actual implementation libraries are created on LoadHookMutator
245 fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
246 fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name())
247 fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
248 fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
249 fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
250 fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
251 fmt.Fprintf(w, "\ttouch $@\n\n")
Inseob Kim988f53c2019-09-16 15:59:01 +0900252 fmt.Fprintf(w, ".PHONY: %s-check-api %s-dump-api\n\n", name, name)
253
254 // dump API rule
255 fmt.Fprintf(w, "%s-dump-api: %s\n\n", name, m.dumpedApiFile.String())
Inseob Kim42882742019-07-30 17:55:33 +0900256
257 // check API rule
258 fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
Inseob Kim42882742019-07-30 17:55:33 +0900259 }}
260}
261
262// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
263// Both Java and C++ modules can link against sysprop_library, and API stability check
264// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
265// is performed.
Inseob Kimc0907f12019-02-08 21:00:45 +0900266func syspropLibraryFactory() android.Module {
267 m := &syspropLibrary{}
268
269 m.AddProperties(
Inseob Kim42882742019-07-30 17:55:33 +0900270 &m.properties,
Inseob Kimc0907f12019-02-08 21:00:45 +0900271 )
Inseob Kim42882742019-07-30 17:55:33 +0900272 android.InitAndroidModule(m)
Inseob Kimc0907f12019-02-08 21:00:45 +0900273 android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
Inseob Kimc0907f12019-02-08 21:00:45 +0900274 return m
275}
276
277func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
Inseob Kim42882742019-07-30 17:55:33 +0900278 if len(m.properties.Srcs) == 0 {
Inseob Kim6e93ac92019-03-21 17:43:49 +0900279 ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
280 }
281
Inseob Kim42882742019-07-30 17:55:33 +0900282 missing_api := false
283
284 for _, txt := range []string{"-current.txt", "-latest.txt"} {
285 path := path.Join(ctx.ModuleDir(), "api", m.BaseModuleName()+txt)
286 file := android.ExistentPathForSource(ctx, path)
287 if !file.Valid() {
288 ctx.ModuleErrorf("API file %#v doesn't exist", path)
289 missing_api = true
290 }
291 }
292
293 if missing_api {
294 script := "build/soong/scripts/gen-sysprop-api-files.sh"
295 p := android.ExistentPathForSource(ctx, script)
296
297 if !p.Valid() {
298 panic(fmt.Sprintf("script file %s doesn't exist", script))
299 }
300
301 ctx.ModuleErrorf("One or more api files are missing. "+
302 "You can create them by:\n"+
303 "%s %q %q", script, ctx.ModuleDir(), m.BaseModuleName())
304 return
Inseob Kimc0907f12019-02-08 21:00:45 +0900305 }
306
307 socSpecific := ctx.SocSpecific()
308 deviceSpecific := ctx.DeviceSpecific()
309 productSpecific := ctx.ProductSpecific()
310
Inseob Kim42882742019-07-30 17:55:33 +0900311 owner := m.properties.Property_owner
312 stub := "sysprop-library-stub-"
Inseob Kimc0907f12019-02-08 21:00:45 +0900313
314 switch owner {
315 case "Platform":
316 // Every partition can access platform-defined properties
Inseob Kim42882742019-07-30 17:55:33 +0900317 stub += "platform"
Inseob Kimc0907f12019-02-08 21:00:45 +0900318 case "Vendor":
319 // System can't access vendor's properties
320 if !socSpecific && !deviceSpecific && !productSpecific {
321 ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
322 "System can't access sysprop_library owned by Vendor")
323 }
Inseob Kim42882742019-07-30 17:55:33 +0900324 stub += "vendor"
Inseob Kimc0907f12019-02-08 21:00:45 +0900325 case "Odm":
326 // Only vendor can access Odm-defined properties
327 if !socSpecific && !deviceSpecific {
328 ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
329 "Odm-defined properties should be accessed only in Vendor or Odm")
330 }
Inseob Kim42882742019-07-30 17:55:33 +0900331 stub += "vendor"
Inseob Kimc0907f12019-02-08 21:00:45 +0900332 default:
333 ctx.PropertyErrorf("property_owner",
334 "Unknown value %s: must be one of Platform, Vendor or Odm", owner)
335 }
336
337 ccProps := struct {
338 Name *string
Inseob Kim42882742019-07-30 17:55:33 +0900339 Srcs []string
Inseob Kimc0907f12019-02-08 21:00:45 +0900340 Soc_specific *bool
341 Device_specific *bool
342 Product_specific *bool
343 Sysprop struct {
344 Platform *bool
345 }
Inseob Kim42882742019-07-30 17:55:33 +0900346 Header_libs []string
347 Shared_libs []string
348 Required []string
349 Recovery *bool
350 Recovery_available *bool
351 Vendor_available *bool
Inseob Kimc0907f12019-02-08 21:00:45 +0900352 }{}
353
354 ccProps.Name = proptools.StringPtr(m.CcModuleName())
Inseob Kim42882742019-07-30 17:55:33 +0900355 ccProps.Srcs = m.properties.Srcs
Inseob Kimc0907f12019-02-08 21:00:45 +0900356 ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
357 ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
358 ccProps.Product_specific = proptools.BoolPtr(productSpecific)
359 ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
Inseob Kimda63a492019-06-10 23:03:16 +0900360 ccProps.Header_libs = []string{"libbase_headers"}
361 ccProps.Shared_libs = []string{"liblog"}
Inseob Kim42882742019-07-30 17:55:33 +0900362 ccProps.Recovery_available = m.properties.Recovery_available
363 ccProps.Vendor_available = m.properties.Vendor_available
364
365 ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProps)
366
Inseob Kim988f53c2019-09-16 15:59:01 +0900367 // internal scope contains all properties
368 // public scope only contains public properties
369 // use public if the owner is different from client
370 scope := "internal"
371 isProduct := ctx.ProductSpecific()
372 isVendor := ctx.SocSpecific()
373 isOwnerPlatform := owner == "Platform"
374
375 if isProduct {
376 // product can't own any sysprop_library now, so product must use public scope
377 scope = "public"
378 } else if isVendor && !isOwnerPlatform {
379 // vendor and odm can't use system's internal property.
380 scope = "public"
381 }
382
383 javaGenProps := struct {
384 Srcs []string
385 Scope string
386 Name *string
387 }{
388 Srcs: m.properties.Srcs,
389 Scope: scope,
390 Name: proptools.StringPtr(m.javaGenModuleName()),
391 }
392
393 ctx.CreateModule(android.ModuleFactoryAdaptor(syspropJavaGenFactory), &javaGenProps)
394
Inseob Kim42882742019-07-30 17:55:33 +0900395 javaProps := struct {
396 Name *string
397 Srcs []string
398 Soc_specific *bool
399 Device_specific *bool
400 Product_specific *bool
Inseob Kim988f53c2019-09-16 15:59:01 +0900401 Required []string
402 Sdk_version *string
403 Installable *bool
404 Libs []string
Inseob Kim42882742019-07-30 17:55:33 +0900405 }{}
406
407 javaProps.Name = proptools.StringPtr(m.BaseModuleName())
Inseob Kim988f53c2019-09-16 15:59:01 +0900408 javaProps.Srcs = []string{":" + *javaGenProps.Name}
Inseob Kim42882742019-07-30 17:55:33 +0900409 javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
410 javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
411 javaProps.Product_specific = proptools.BoolPtr(productSpecific)
412 javaProps.Installable = m.properties.Installable
Inseob Kim42882742019-07-30 17:55:33 +0900413 javaProps.Sdk_version = proptools.StringPtr("core_current")
Inseob Kim42882742019-07-30 17:55:33 +0900414 javaProps.Libs = []string{stub}
415
416 ctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProps)
Inseob Kimc0907f12019-02-08 21:00:45 +0900417}
Inseob Kim988f53c2019-09-16 15:59:01 +0900418
419func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
420 if m, ok := ctx.Module().(*syspropLibrary); ok {
421 ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
422 }
423}