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

Commit ce918b02 authored by Paul Duffin's avatar Paul Duffin
Browse files

Copy boot dex jars from prebuilt art-bootclasspath-fragment if preferred

Previously, the boot dex jars were only copied to the predefined
locations used by the build from the source art-bootclasspath-fragment
if it was preferred, otherwise no files were copied. That caused build
failures when attempting to build with ART prebuilts. This change
copies the files from prebuilts too.

Bug: 177892522
Bug: 189298093
Test: m nothing
      m droid SOONG_CONFIG_art_module_source_build=false SKIP_BOOT_JARS_CHECK=true
      - the previous command does not work but this change does fix one
        of the issues reported.
Change-Id: I35b37355170546daf6ecac2134d1ca9a73d0e3bc
parent 94b2e705
Loading
Loading
Loading
Loading
+87 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ package apex

import (
	"fmt"
	"sort"
	"strings"
	"testing"

@@ -359,6 +360,19 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {

	addPrebuilt := func(prefer bool, contents ...string) android.FixturePreparer {
		text := fmt.Sprintf(`
			prebuilt_apex {
				name: "com.android.art",
				arch: {
					arm64: {
						src: "com.android.art-arm64.apex",
					},
					arm: {
						src: "com.android.art-arm.apex",
					},
				},
				exported_bootclasspath_fragments: ["mybootclasspathfragment"],
			}

			prebuilt_bootclasspath_fragment {
				name: "mybootclasspathfragment",
				image_name: "art",
@@ -372,7 +386,47 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
		return android.FixtureAddTextFile("prebuilts/module_sdk/art/Android.bp", text)
	}

	t.Run("boot image files", func(t *testing.T) {
	t.Run("boot image files from source", func(t *testing.T) {
		result := android.GroupFixturePreparers(
			commonPreparer,

			// Configure some libraries in the art bootclasspath_fragment that match the source
			// bootclasspath_fragment's contents property.
			java.FixtureConfigureBootJars("com.android.art:foo", "com.android.art:bar"),
			addSource("foo", "bar"),
		).RunTest(t)

		ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
			"etc/classpaths/bootclasspath.pb",
			"javalib/arm/boot.art",
			"javalib/arm/boot.oat",
			"javalib/arm/boot.vdex",
			"javalib/arm/boot-bar.art",
			"javalib/arm/boot-bar.oat",
			"javalib/arm/boot-bar.vdex",
			"javalib/arm64/boot.art",
			"javalib/arm64/boot.oat",
			"javalib/arm64/boot.vdex",
			"javalib/arm64/boot-bar.art",
			"javalib/arm64/boot-bar.oat",
			"javalib/arm64/boot-bar.vdex",
			"javalib/bar.jar",
			"javalib/foo.jar",
		})

		java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
			`bar`,
			`com.android.art.key`,
			`mybootclasspathfragment`,
		})

		// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
		// locations for the art image.
		module := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
	})

	t.Run("boot image files with preferred prebuilt", func(t *testing.T) {
		result := android.GroupFixturePreparers(
			commonPreparer,

@@ -407,7 +461,13 @@ func TestBootclasspathFragmentInArtApex(t *testing.T) {
			`bar`,
			`com.android.art.key`,
			`mybootclasspathfragment`,
			`prebuilt_com.android.art`,
		})

		// Make sure that the prebuilt bootclasspath_fragment copies its dex files to the predefined
		// locations for the art image.
		module := result.ModuleForTests("prebuilt_mybootclasspathfragment", "android_common_com.android.art")
		checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
	})

	t.Run("source with inconsistency between config and contents", func(t *testing.T) {
@@ -528,11 +588,36 @@ func TestBootclasspathFragmentInPrebuiltArtApex(t *testing.T) {
		`prebuilt_mybootclasspathfragment`,
	})

	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common", []string{
	java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_com.android.art", []string{
		`dex2oatd`,
		`prebuilt_bar`,
		`prebuilt_foo`,
	})

	module := result.ModuleForTests("mybootclasspathfragment", "android_common_com.android.art")
	checkCopiesToPredefinedLocationForArt(t, result.Config, module, "bar", "foo")
}

// checkCopiesToPredefinedLocationForArt checks that the supplied modules are copied to the
// predefined locations of boot dex jars used as inputs for the ART boot image.
func checkCopiesToPredefinedLocationForArt(t *testing.T, config android.Config, module android.TestingModule, modules ...string) {
	t.Helper()
	bootJarLocations := []string{}
	for _, output := range module.AllOutputs() {
		output = android.StringRelativeToTop(config, output)
		if strings.HasPrefix(output, "out/soong/test_device/dex_artjars_input/") {
			bootJarLocations = append(bootJarLocations, output)
		}
	}

	sort.Strings(bootJarLocations)
	expected := []string{}
	for _, m := range modules {
		expected = append(expected, fmt.Sprintf("out/soong/test_device/dex_artjars_input/%s.jar", m))
	}
	sort.Strings(expected)

	android.AssertArrayString(t, "copies to predefined locations for art", expected, bootJarLocations)
}

func TestBootclasspathFragmentContentsNoName(t *testing.T) {
+30 −4
Original line number Diff line number Diff line
@@ -409,6 +409,13 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
		// Perform hidden API processing.
		hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)

		if imageConfig != nil {
			if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
				// Copy the dex jars of this fragment's content modules to their predefined locations.
				copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
			}
		}

		// A prebuilt fragment cannot contribute to an apex.
		if !android.IsModulePrebuilt(ctx.Module()) {
			// Provide the apex content info.
@@ -417,6 +424,29 @@ func (b *BootclasspathFragmentModule) GenerateAndroidBuildActions(ctx android.Mo
	}
}

// shouldCopyBootFilesToPredefinedLocations determines whether the current module should copy boot
// files, e.g. boot dex jars or boot image files, to the predefined location expected by the rest
// of the build.
//
// This ensures that only a single module will copy its files to the image configuration.
func shouldCopyBootFilesToPredefinedLocations(ctx android.ModuleContext, imageConfig *bootImageConfig) bool {
	// Bootclasspath fragment modules that are for the platform do not produce boot related files.
	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
	if apexInfo.IsForPlatform() {
		return false
	}

	// If the image configuration has no modules specified then it means that the build has been
	// configured to build something other than a boot image, e.g. an sdk, so do not try and copy the
	// files.
	if imageConfig.modules.Len() == 0 {
		return false
	}

	// Only copy files from the module that is preferred.
	return isActiveModule(ctx.Module())
}

// provideApexContentInfo creates, initializes and stores the apex content info for use by other
// modules.
func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, contents []android.Module, hiddenAPIOutput *HiddenAPIOutput) {
@@ -635,10 +665,6 @@ func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.
		return false
	}

	// Copy the dex jars of this fragment's content modules to their predefined locations.
	bootDexJarByModule := extractEncodedDexJarsFromModules(ctx, contents)
	copyBootJarsToPredefinedLocations(ctx, bootDexJarByModule, imageConfig.dexPathsByModule)

	// Build a profile for the image config and then use that to build the boot image.
	profile := bootImageProfileRule(ctx, imageConfig)
	buildBootImage(ctx, imageConfig, profile)