Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4aea00ec authored by Paul Duffin's avatar Paul Duffin Committed by Gerrit Code Review
Browse files

Merge "Move boot jars package check into platform_bootclasspath"

parents 909a2fd0 c8ead41b
Loading
Loading
Loading
Loading
+7 −94
Original line number Diff line number Diff line
@@ -18,37 +18,6 @@ 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.
@@ -59,73 +28,17 @@ func isActiveModule(module android.Module) bool {
	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.InApexModule(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
			}
		}
	})

// buildRuleForBootJarsPackageCheck generates the build rule to perform the boot jars package
// check.
func buildRuleForBootJarsPackageCheck(ctx android.ModuleContext, bootDexJarByModule bootDexJarByModule) {
	timestamp := android.PathForOutput(ctx, "boot-jars-package-check/stamp")

	rule := android.NewRuleBuilder(pctx, ctx)
	checkBootJars := rule.Command().BuiltTool("check_boot_jars").
	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)
		Input(android.PathForSource(ctx, "build/soong/scripts/check_boot_jars/package_allowed_list.txt")).
		Inputs(bootDexJarByModule.bootDexJars()).
		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.
+6 −3
Original line number Diff line number Diff line
@@ -189,7 +189,8 @@ func (b *platformBootclasspathModule) GenerateAndroidBuildActions(ctx android.Mo

	b.generateClasspathProtoBuildActions(ctx)

	b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
	bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
	buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)

	// Nothing to do if skipping the dexpreopt of boot image jars.
	if SkipDexpreoptBootJars(ctx) {
@@ -258,7 +259,7 @@ func (b *platformBootclasspathModule) getImageConfig(ctx android.EarlyModuleCont
}

// generateHiddenAPIBuildActions generates all the hidden API related build rules.
func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) {
func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.ModuleContext, modules []android.Module, fragments []android.Module) bootDexJarByModule {

	// Save the paths to the monolithic files for retrieval via OutputFiles().
	b.hiddenAPIFlagsCSV = hiddenAPISingletonPaths(ctx).flags
@@ -276,7 +277,7 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
				Output: path,
			})
		}
		return
		return nil
	}

	monolithicInfo := b.createAndProvideMonolithicHiddenAPIInfo(ctx, fragments)
@@ -322,6 +323,8 @@ func (b *platformBootclasspathModule) generateHiddenAPIBuildActions(ctx android.
	// jars.
	indexCSV := hiddenAPISingletonPaths(ctx).index
	buildRuleToGenerateIndex(ctx, "monolithic hidden API index", classesJars, indexCSV)

	return bootDexJarByModule
}

// createAndProvideMonolithicHiddenAPIInfo creates a MonolithicHiddenAPIInfo and provides it for
+21 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ func fixtureAddPlatformBootclasspathForBootclasspathFragment(apex, fragment stri
			}
		`, apex, fragment)),
		android.FixtureAddFile("frameworks/base/config/boot-profile.txt", nil),
		android.FixtureAddFile("build/soong/scripts/check_boot_jars/package_allowed_list.txt", nil),
	)
}

@@ -173,9 +174,29 @@ sdk_snapshot {
.intermediates/mybootlib/android_common/javac/mybootlib.jar -> java/mybootlib.jar
`),
		snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),

		// Check the behavior of the snapshot without the source.
		snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
			// Make sure that the boot jars package check rule includes the dex jar retrieved from the prebuilt apex.
			checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/mybootlib.jar")
		}),

		snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
		snapshotTestPreparer(checkSnapshotPreferredWithSource, preparerForSnapshot),
	)

	// Make sure that the boot jars package check rule includes the dex jar created from the source.
	checkBootJarsPackageCheckRule(t, result, "out/soong/.intermediates/mybootlib/android_common_apex10000/aligned/mybootlib.jar")
}

// checkBootJarsPackageCheckRule checks that the supplied module is an input to the boot jars
// package check rule.
func checkBootJarsPackageCheckRule(t *testing.T, result *android.TestResult, expectedModule string) {
	platformBcp := result.ModuleForTests("platform-bootclasspath", "android_common")
	bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
	command := bootJarsCheckRule.RuleParams.Command
	expectedCommandArgs := " out/soong/host/linux-x86/bin/dexdump build/soong/scripts/check_boot_jars/package_allowed_list.txt " + expectedModule + " &&"
	android.AssertStringDoesContain(t, "boot jars package check", command, expectedCommandArgs)
}

func TestSnapshotWithBootClasspathFragment_Contents(t *testing.T) {