blob: 7abda80314e93ba25c31a004aefb5ba64a003f1b [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
Martin Stjernholm1dc0d6d2021-01-17 21:05:12 +000052// isActiveModule returns true if the given module should be considered for boot
53// jars, i.e. if it's enabled and the preferred one in case of source and
54// prebuilt alternatives.
55func isActiveModule(module android.Module) bool {
56 if !module.Enabled() {
57 return false
58 }
Paul Duffine1d38372021-04-02 10:35:24 +010059 return android.IsModulePreferred(module)
Martin Stjernholm1dc0d6d2021-01-17 21:05:12 +000060}
61
Paul Duffin9a89a2a2020-10-28 19:20:06 +000062func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
63 config := ctx.Config()
64 if config.SkipBootJarsCheck() {
65 return
66 }
67
Martin Stjernholm1dc0d6d2021-01-17 21:05:12 +000068 // Populate a map from module name to APEX from the boot jars. If there is a
69 // problem such as duplicate modules then fail and return immediately. Note
70 // that both module and APEX names are tracked by base names here, so we need
71 // to be careful to remove "prebuilt_" prefixes when comparing them with
72 // actual modules and APEX bundles.
Paul Duffin9a89a2a2020-10-28 19:20:06 +000073 moduleToApex := make(map[string]string)
74 if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") ||
75 !populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") {
76 return
77 }
78
79 // Map from module name to the correct apex variant.
80 nameToApexVariant := make(map[string]android.Module)
81
82 // Scan all the modules looking for the module/apex variants corresponding to the
83 // boot jars.
84 ctx.VisitAllModules(func(module android.Module) {
Martin Stjernholm1dc0d6d2021-01-17 21:05:12 +000085 if !isActiveModule(module) {
86 return
87 }
88
89 name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module))
Paul Duffin9a89a2a2020-10-28 19:20:06 +000090 if apex, ok := moduleToApex[name]; ok {
91 apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
Jiyong Park78349b52021-05-12 17:13:56 +090092 if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexModule(apex) {
Paul Duffin9a89a2a2020-10-28 19:20:06 +000093 // The module name/apex variant should be unique in the system but double check
94 // just in case something has gone wrong.
95 if existing, ok := nameToApexVariant[name]; ok {
96 ctx.Errorf("found multiple variants matching %s:%s: %q and %q", apex, name, existing, module)
97 }
98 nameToApexVariant[name] = module
99 }
100 }
101 })
102
103 timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")
104
Colin Crossf1a035e2020-11-16 17:32:30 -0800105 rule := android.NewRuleBuilder(pctx, ctx)
106 checkBootJars := rule.Command().BuiltTool("check_boot_jars").
Paul Duffin2d8e1a72020-10-29 12:56:09 +0000107 Input(ctx.Config().HostToolPath(ctx, "dexdump")).
Paul Duffin9a89a2a2020-10-28 19:20:06 +0000108 Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt"))
109
110 // If this is not an unbundled build and missing dependencies are not allowed
111 // then all the boot jars listed must have been found.
112 strict := !config.UnbundledBuild() && !config.AllowMissingDependencies()
113
114 // Iterate over the module names on the boot classpath in order
115 for _, name := range android.SortedStringKeys(moduleToApex) {
116 if apexVariant, ok := nameToApexVariant[name]; ok {
Paul Duffin2d8e1a72020-10-29 12:56:09 +0000117 if dep, ok := apexVariant.(interface{ DexJarBuildPath() android.Path }); ok {
118 // Add the dex implementation jar for the module to be checked.
119 checkBootJars.Input(dep.DexJarBuildPath())
Paul Duffin9a89a2a2020-10-28 19:20:06 +0000120 } else {
121 ctx.Errorf("module %q is of type %q which is not supported as a boot jar", name, ctx.ModuleType(apexVariant))
122 }
123 } else if strict {
124 ctx.Errorf("boot jars package check failed as it could not find module %q for apex %q", name, moduleToApex[name])
125 }
126 }
127
128 checkBootJars.Text("&& touch").Output(timestamp)
Colin Crossf1a035e2020-11-16 17:32:30 -0800129 rule.Build("boot_jars_package_check", "check boot jar packages")
Paul Duffin9a89a2a2020-10-28 19:20:06 +0000130
131 // The check-boot-jars phony target depends on the timestamp created if the check succeeds.
132 ctx.Phony("check-boot-jars", timestamp)
133
134 // The droidcore phony target depends on the check-boot-jars phony target
135 ctx.Phony("droidcore", android.PathForPhony(ctx, "check-boot-jars"))
136}