blob: e70654781c9665879fd331f92d0fbacc025f831e [file] [log] [blame]
Paul Duffin9a89a2a2020-10-28 19:20:06 +00001// Copyright 2020 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)
20
21func init() {
22 android.RegisterSingletonType("boot_jars", bootJarsSingletonFactory)
23}
24
25func bootJarsSingletonFactory() android.Singleton {
26 return &bootJarsSingleton{}
27}
28
29type bootJarsSingleton struct{}
30
31func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex map[string]string, list android.ConfiguredJarList, name string) bool {
32 for i := 0; i < list.Len(); i++ {
33 module := list.Jar(i)
34 // Ignore jacocoagent it is only added when instrumenting and so has no impact on
35 // app compatibility.
36 if module == "jacocoagent" {
37 continue
38 }
39 apex := list.Apex(i)
40 if existing, ok := moduleToApex[module]; ok {
41 ctx.Errorf("Configuration property %q is invalid as it contains multiple references to module (%s) in APEXes (%s and %s)",
42 module, existing, apex)
43 return false
44 }
45
46 moduleToApex[module] = apex
47 }
48
49 return true
50}
51
52func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
53 config := ctx.Config()
54 if config.SkipBootJarsCheck() {
55 return
56 }
57
58 // Populate a map from module name to APEX from the boot jars. If there is a problem
59 // such as duplicate modules then fail and return immediately.
60 moduleToApex := make(map[string]string)
61 if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") ||
62 !populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") {
63 return
64 }
65
66 // Map from module name to the correct apex variant.
67 nameToApexVariant := make(map[string]android.Module)
68
69 // Scan all the modules looking for the module/apex variants corresponding to the
70 // boot jars.
71 ctx.VisitAllModules(func(module android.Module) {
72 name := ctx.ModuleName(module)
73 if apex, ok := moduleToApex[name]; ok {
74 apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
75 if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApex(apex) {
76 // The module name/apex variant should be unique in the system but double check
77 // just in case something has gone wrong.
78 if existing, ok := nameToApexVariant[name]; ok {
79 ctx.Errorf("found multiple variants matching %s:%s: %q and %q", apex, name, existing, module)
80 }
81 nameToApexVariant[name] = module
82 }
83 }
84 })
85
86 timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")
87
88 rule := android.NewRuleBuilder()
89 checkBootJars := rule.Command().BuiltTool(ctx, "check_boot_jars").
Paul Duffin2d8e1a72020-10-29 12:56:09 +000090 Input(ctx.Config().HostToolPath(ctx, "dexdump")).
Paul Duffin9a89a2a2020-10-28 19:20:06 +000091 Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt"))
92
93 // If this is not an unbundled build and missing dependencies are not allowed
94 // then all the boot jars listed must have been found.
95 strict := !config.UnbundledBuild() && !config.AllowMissingDependencies()
96
97 // Iterate over the module names on the boot classpath in order
98 for _, name := range android.SortedStringKeys(moduleToApex) {
99 if apexVariant, ok := nameToApexVariant[name]; ok {
Paul Duffin2d8e1a72020-10-29 12:56:09 +0000100 if dep, ok := apexVariant.(interface{ DexJarBuildPath() android.Path }); ok {
101 // Add the dex implementation jar for the module to be checked.
102 checkBootJars.Input(dep.DexJarBuildPath())
Paul Duffin9a89a2a2020-10-28 19:20:06 +0000103 } else {
104 ctx.Errorf("module %q is of type %q which is not supported as a boot jar", name, ctx.ModuleType(apexVariant))
105 }
106 } else if strict {
107 ctx.Errorf("boot jars package check failed as it could not find module %q for apex %q", name, moduleToApex[name])
108 }
109 }
110
111 checkBootJars.Text("&& touch").Output(timestamp)
112 rule.Build(pctx, ctx, "boot_jars_package_check", "check boot jar packages")
113
114 // The check-boot-jars phony target depends on the timestamp created if the check succeeds.
115 ctx.Phony("check-boot-jars", timestamp)
116
117 // The droidcore phony target depends on the check-boot-jars phony target
118 ctx.Phony("droidcore", android.PathForPhony(ctx, "check-boot-jars"))
119}