.. in preparation for the upcoming change. This change doesn't alter any behavior. InApexes is a misleading name. People expects that it has the list of soong module names of the APEXes that a module is part of. So, for example, `core-oj` is a part of both `com.android.art` and `com.google.android.art`. However, in reality, that's not true. The field has `com.android.art` only. This is because the two APEXes (android and Google) have the same apex name which is `com.android.art`. That apex name is used in various places like the `apex_available` and allows us to keep using the same name regardless of whether the APEX is overridden or not. However, this is causing problems in some cases where the exact list of soong module names is required. The upcoming change will add a new field to handle the case and the new field actually will get the name 'InApexes'. So, the existing field is renamed to a less misleading name `InApexVariants`. Cherry-picked from https://r.android.com/1710528. Bug: 180325915 Test: m nothing Change-Id: I0c73361b452eddb812acd5ebef5dcedaab382436 Merged-In: I0c73361b452eddb812acd5ebef5dcedaab382436
137 lines
5.0 KiB
Go
137 lines
5.0 KiB
Go
// Copyright 2020 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package java
|
|
|
|
import (
|
|
"android/soong/android"
|
|
)
|
|
|
|
func init() {
|
|
android.RegisterSingletonType("boot_jars", bootJarsSingletonFactory)
|
|
}
|
|
|
|
func bootJarsSingletonFactory() android.Singleton {
|
|
return &bootJarsSingleton{}
|
|
}
|
|
|
|
type bootJarsSingleton struct{}
|
|
|
|
func populateMapFromConfiguredJarList(ctx android.SingletonContext, moduleToApex map[string]string, list android.ConfiguredJarList, name string) bool {
|
|
for i := 0; i < list.Len(); i++ {
|
|
module := list.Jar(i)
|
|
// Ignore jacocoagent it is only added when instrumenting and so has no impact on
|
|
// app compatibility.
|
|
if module == "jacocoagent" {
|
|
continue
|
|
}
|
|
apex := list.Apex(i)
|
|
if existing, ok := moduleToApex[module]; ok {
|
|
ctx.Errorf("Configuration property %q is invalid as it contains multiple references to module (%s) in APEXes (%s and %s)",
|
|
module, existing, apex)
|
|
return false
|
|
}
|
|
|
|
moduleToApex[module] = apex
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// isActiveModule returns true if the given module should be considered for boot
|
|
// jars, i.e. if it's enabled and the preferred one in case of source and
|
|
// prebuilt alternatives.
|
|
func isActiveModule(module android.Module) bool {
|
|
if !module.Enabled() {
|
|
return false
|
|
}
|
|
return android.IsModulePreferred(module)
|
|
}
|
|
|
|
func (b *bootJarsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
config := ctx.Config()
|
|
if config.SkipBootJarsCheck() {
|
|
return
|
|
}
|
|
|
|
// Populate a map from module name to APEX from the boot jars. If there is a
|
|
// problem such as duplicate modules then fail and return immediately. Note
|
|
// that both module and APEX names are tracked by base names here, so we need
|
|
// to be careful to remove "prebuilt_" prefixes when comparing them with
|
|
// actual modules and APEX bundles.
|
|
moduleToApex := make(map[string]string)
|
|
if !populateMapFromConfiguredJarList(ctx, moduleToApex, config.NonUpdatableBootJars(), "BootJars") ||
|
|
!populateMapFromConfiguredJarList(ctx, moduleToApex, config.UpdatableBootJars(), "UpdatableBootJars") {
|
|
return
|
|
}
|
|
|
|
// Map from module name to the correct apex variant.
|
|
nameToApexVariant := make(map[string]android.Module)
|
|
|
|
// Scan all the modules looking for the module/apex variants corresponding to the
|
|
// boot jars.
|
|
ctx.VisitAllModules(func(module android.Module) {
|
|
if !isActiveModule(module) {
|
|
return
|
|
}
|
|
|
|
name := android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName(module))
|
|
if apex, ok := moduleToApex[name]; ok {
|
|
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
|
|
if (apex == "platform" && apexInfo.IsForPlatform()) || apexInfo.InApexVariantByBaseName(apex) {
|
|
// The module name/apex variant should be unique in the system but double check
|
|
// just in case something has gone wrong.
|
|
if existing, ok := nameToApexVariant[name]; ok {
|
|
ctx.Errorf("found multiple variants matching %s:%s: %q and %q", apex, name, existing, module)
|
|
}
|
|
nameToApexVariant[name] = module
|
|
}
|
|
}
|
|
})
|
|
|
|
timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")
|
|
|
|
rule := android.NewRuleBuilder(pctx, ctx)
|
|
checkBootJars := rule.Command().BuiltTool("check_boot_jars").
|
|
Input(ctx.Config().HostToolPath(ctx, "dexdump")).
|
|
Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt"))
|
|
|
|
// If this is not an unbundled build and missing dependencies are not allowed
|
|
// then all the boot jars listed must have been found.
|
|
strict := !config.UnbundledBuild() && !config.AllowMissingDependencies()
|
|
|
|
// Iterate over the module names on the boot classpath in order
|
|
for _, name := range android.SortedStringKeys(moduleToApex) {
|
|
if apexVariant, ok := nameToApexVariant[name]; ok {
|
|
if dep, ok := apexVariant.(interface{ DexJarBuildPath() android.Path }); ok {
|
|
// Add the dex implementation jar for the module to be checked.
|
|
checkBootJars.Input(dep.DexJarBuildPath())
|
|
} else {
|
|
ctx.Errorf("module %q is of type %q which is not supported as a boot jar", name, ctx.ModuleType(apexVariant))
|
|
}
|
|
} else if strict {
|
|
ctx.Errorf("boot jars package check failed as it could not find module %q for apex %q", name, moduleToApex[name])
|
|
}
|
|
}
|
|
|
|
checkBootJars.Text("&& touch").Output(timestamp)
|
|
rule.Build("boot_jars_package_check", "check boot jar packages")
|
|
|
|
// The check-boot-jars phony target depends on the timestamp created if the check succeeds.
|
|
ctx.Phony("check-boot-jars", timestamp)
|
|
|
|
// The droidcore phony target depends on the check-boot-jars phony target
|
|
ctx.Phony("droidcore", android.PathForPhony(ctx, "check-boot-jars"))
|
|
}
|