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

Commit 4709929c authored by Jiakai Zhang's avatar Jiakai Zhang Committed by Gerrit Code Review
Browse files

Merge changes from topic "boot-image-mainline"

* changes:
  Generate a boot image extension for mainline BCP jars.
  Refactor platform_bootclasspath to support multiple boot images.
  Refactor dexpreopt for boot jars to allow more complex dependencies.
parents 8ecedd4d 3830308f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -29,6 +29,15 @@ func CopyOf(s []string) []string {
	return append([]string(nil), s...)
}

// Concat returns a new slice concatenated from the two input slices. It does not change the input
// slices.
func Concat[T any](s1, s2 []T) []T {
	res := make([]T, 0, len(s1)+len(s2))
	res = append(res, s1...)
	res = append(res, s2...)
	return res
}

// JoinWithPrefix prepends the prefix to each string in the list and
// returns them joined together with " " as separator.
func JoinWithPrefix(strs []string, prefix string) string {
+6 −0
Original line number Diff line number Diff line
@@ -293,6 +293,12 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
	isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx))

	bootImage := defaultBootImageConfig(ctx)
	// When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline
	// boot jars into bootclasspath, so we should include the mainline boot image as well because it's
	// generated from those jars.
	if global.PreoptWithUpdatableBcp {
		bootImage = mainlineBootImageConfig(ctx)
	}
	dexFiles, dexLocations := bcpForDexpreopt(ctx, global.PreoptWithUpdatableBcp)

	targets := ctx.MultiTargets()
+21 −11
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ package java

import (
	"path/filepath"
	"sort"
	"strings"

	"android/soong/android"
@@ -312,17 +313,17 @@ type bootImageVariant struct {
	// All the files that constitute this image variant, i.e. .art, .oat and .vdex files.
	imagesDeps android.OutputPaths

	// The path to the primary image variant's imagePathOnHost field, where primary image variant
	// The path to the base image variant's imagePathOnHost field, where base image variant
	// means the image variant that this extends.
	//
	// This is only set for a variant of an image that extends another image.
	primaryImages android.OutputPath
	baseImages android.OutputPaths

	// The paths to the primary image variant's imagesDeps field, where primary image variant
	// The paths to the base image variant's imagesDeps field, where base image variant
	// means the image variant that this extends.
	//
	// This is only set for a variant of an image that extends another image.
	primaryImagesDeps android.Paths
	baseImagesDeps android.Paths

	// Rules which should be used in make to install the outputs on host.
	//
@@ -511,8 +512,13 @@ func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonC

	defaultImageConfig := defaultBootImageConfig(ctx)
	d.defaultBootImage = defaultImageConfig
	artBootImageConfig := artBootImageConfig(ctx)
	d.otherImages = []*bootImageConfig{artBootImageConfig}
	imageConfigs := genBootImageConfigs(ctx)
	d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
	for _, config := range imageConfigs {
		if config != defaultImageConfig {
			d.otherImages = append(d.otherImages, config)
		}
	}
}

// shouldBuildBootImages determines whether boot images should be built.
@@ -708,9 +714,11 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
	}

	if image.extends != nil {
		// It is a boot image extension, so it needs the boot image it depends on (in this case the
		// primary ART APEX image).
		artImage := image.primaryImages
		// It is a boot image extension, so it needs the boot images that it depends on.
		baseImageLocations := make([]string, 0, len(image.baseImages))
		for _, image := range image.baseImages {
			baseImageLocations = append(baseImageLocations, dexpreopt.PathToLocation(image, arch))
		}
		cmd.
			Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
			Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
@@ -718,11 +726,11 @@ func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, p
			// dex2oat will reconstruct the path to the actual file when it needs it. As the actual path
			// to the file cannot be passed to the command make sure to add the actual path as an Implicit
			// dependency to ensure that it is built before the command runs.
			FlagWithArg("--boot-image=", dexpreopt.PathToLocation(artImage, arch)).Implicit(artImage).
			FlagWithList("--boot-image=", baseImageLocations, ":").Implicits(image.baseImages.Paths()).
			// Similarly, the dex2oat tool will automatically find the paths to other files in the base
			// boot image so make sure to add them as implicit dependencies to ensure that they are built
			// before this command is run.
			Implicits(image.primaryImagesDeps)
			Implicits(image.baseImagesDeps)
	} else {
		// It is a primary image, so it needs a base address.
		cmd.FlagWithArg("--base=", ctx.Config().LibartImgDeviceBaseAddress())
@@ -1021,6 +1029,8 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) {
			ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE"+current.name, strings.Join(imageLocationsOnDevice, ":"))
			ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+current.name, current.zip.String())
		}
		// Ensure determinism.
		sort.Strings(imageNames)
		ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
	}
}
+52 −13
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ var (
	bootImageConfigRawKey  = android.NewOnceKey("bootImageConfigRaw")
	artBootImageName       = "art"
	frameworkBootImageName = "boot"
	mainlineBootImageName  = "mainline"
	bootImageStem          = "boot"
)

func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig {
@@ -52,14 +54,16 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig

		artModules := global.ArtApexJars
		frameworkModules := global.BootJars.RemoveList(artModules)
		mainlineBcpModules := global.ApexBootJars
		frameworkSubdir := "system/framework"

		// ART config for the primary boot image in the ART apex.
		// It includes the Core Libraries.
		artCfg := bootImageConfig{
			name:                     artBootImageName,
			stem:                     "boot",
			stem:                     bootImageStem,
			installDirOnHost:         "apex/art_boot_images/javalib",
			installDirOnDevice:       "system/framework",
			installDirOnDevice:       frameworkSubdir,
			profileInstallPathInApex: "etc/boot-image.prof",
			modules:                  artModules,
			preloadedClassesFile:     "art/build/boot/preloaded-classes",
@@ -68,11 +72,10 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig

		// Framework config for the boot image extension.
		// It includes framework libraries and depends on the ART config.
		frameworkSubdir := "system/framework"
		frameworkCfg := bootImageConfig{
			extends:              &artCfg,
			name:                 frameworkBootImageName,
			stem:                 "boot",
			stem:                 bootImageStem,
			installDirOnHost:     frameworkSubdir,
			installDirOnDevice:   frameworkSubdir,
			modules:              frameworkModules,
@@ -80,9 +83,20 @@ func genBootImageConfigRaw(ctx android.PathContext) map[string]*bootImageConfig
			compilerFilter:       "speed-profile",
		}

		mainlineCfg := bootImageConfig{
			extends:            &frameworkCfg,
			name:               mainlineBootImageName,
			stem:               bootImageStem,
			installDirOnHost:   frameworkSubdir,
			installDirOnDevice: frameworkSubdir,
			modules:            mainlineBcpModules,
			compilerFilter:     "verify",
		}

		return map[string]*bootImageConfig{
			artBootImageName:       &artCfg,
			frameworkBootImageName: &frameworkCfg,
			mainlineBootImageName:  &mainlineCfg,
		}
	}).(map[string]*bootImageConfig)
}
@@ -94,10 +108,7 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
		deviceDir := android.PathForOutput(ctx, ctx.Config().DeviceName())

		configs := genBootImageConfigRaw(ctx)
		artCfg := configs[artBootImageName]
		frameworkCfg := configs[frameworkBootImageName]

		// common to all configs
		for _, c := range configs {
			c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars")
			c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped")
@@ -133,18 +144,42 @@ func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
			c.zip = c.dir.Join(ctx, c.name+".zip")
		}

		// specific to the framework config
		frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
		for i := range targets {
			frameworkCfg.variants[i].primaryImages = artCfg.variants[i].imagePathOnHost
			frameworkCfg.variants[i].primaryImagesDeps = artCfg.variants[i].imagesDeps.Paths()
			frameworkCfg.variants[i].dexLocationsDeps = append(artCfg.variants[i].dexLocations, frameworkCfg.variants[i].dexLocationsDeps...)
		visited := make(map[string]bool)
		for _, c := range configs {
			calculateDepsRecursive(c, targets, visited)
		}

		return configs
	}).(map[string]*bootImageConfig)
}

// calculateDepsRecursive calculates the dependencies of the given boot image config and all its
// ancestors, if they are not visited.
// The boot images are supposed to form a tree, where the root is the primary boot image. We do not
// expect loops (e.g., A extends B, B extends C, C extends A), and we let them crash soong with a
// stack overflow.
// Note that a boot image config only has a pointer to the parent, not to children. Therefore, we
// first go up through the parent chain, and then go back down to visit every code along the path.
// `visited` is a map where a key is a boot image name and the value indicates whether the boot
// image config is visited. The boot image names are guaranteed to be unique because they come from
// `genBootImageConfigRaw` above, which also returns a map and would fail in the first place if the
// names were not unique.
func calculateDepsRecursive(c *bootImageConfig, targets []android.Target, visited map[string]bool) {
	if c.extends == nil || visited[c.name] {
		return
	}
	if c.extends.extends != nil {
		calculateDepsRecursive(c.extends, targets, visited)
	}
	visited[c.name] = true
	c.dexPathsDeps = android.Concat(c.extends.dexPathsDeps, c.dexPathsDeps)
	for i := range targets {
		c.variants[i].baseImages = android.Concat(c.extends.variants[i].baseImages, android.OutputPaths{c.extends.variants[i].imagePathOnHost})
		c.variants[i].baseImagesDeps = android.Concat(c.extends.variants[i].baseImagesDeps, c.extends.variants[i].imagesDeps.Paths())
		c.variants[i].dexLocationsDeps = android.Concat(c.extends.variants[i].dexLocationsDeps, c.variants[i].dexLocationsDeps)
	}
}

func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
	return genBootImageConfigs(ctx)[artBootImageName]
}
@@ -153,6 +188,10 @@ func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
	return genBootImageConfigs(ctx)[frameworkBootImageName]
}

func mainlineBootImageConfig(ctx android.PathContext) *bootImageConfig {
	return genBootImageConfigs(ctx)[mainlineBootImageName]
}

// Apex boot config allows to access build/install paths of apex boot jars without going
// through the usual trouble of registering dependencies on those modules and extracting build paths
// from those dependencies.
+2 −0
Original line number Diff line number Diff line
@@ -28,8 +28,10 @@ func TestBootImageConfig(t *testing.T) {

	result := android.GroupFixturePreparers(
		PrepareForBootImageConfigTest,
		PrepareApexBootJarConfigs,
	).RunTest(t)

	CheckArtBootImageConfig(t, result)
	CheckFrameworkBootImageConfig(t, result)
	CheckMainlineBootImageConfig(t, result)
}
Loading