| Paul Duffin | 9a89a2a | 2020-10-28 19:20:06 +0000 | [diff] [blame] | 1 | // 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 |  | 
|  | 15 | package java | 
|  | 16 |  | 
|  | 17 | import ( | 
|  | 18 | "android/soong/android" | 
|  | 19 | ) | 
|  | 20 |  | 
|  | 21 | func init() { | 
|  | 22 | android.RegisterSingletonType("boot_jars", bootJarsSingletonFactory) | 
|  | 23 | } | 
|  | 24 |  | 
|  | 25 | func bootJarsSingletonFactory() android.Singleton { | 
|  | 26 | return &bootJarsSingleton{} | 
|  | 27 | } | 
|  | 28 |  | 
|  | 29 | type bootJarsSingleton struct{} | 
|  | 30 |  | 
|  | 31 | func 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 |  | 
|  | 52 | func (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 Duffin | 2d8e1a7 | 2020-10-29 12:56:09 +0000 | [diff] [blame] | 90 | Input(ctx.Config().HostToolPath(ctx, "dexdump")). | 
| Paul Duffin | 9a89a2a | 2020-10-28 19:20:06 +0000 | [diff] [blame] | 91 | 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 Duffin | 2d8e1a7 | 2020-10-29 12:56:09 +0000 | [diff] [blame] | 100 | 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 Duffin | 9a89a2a | 2020-10-28 19:20:06 +0000 | [diff] [blame] | 103 | } 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 | } |