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

Commit 6ea9e45d authored by satayev's avatar satayev Committed by Automerger Merge Worker
Browse files

Merge "Add classpath fragment property to skip proto generation." am: f45966f3

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1738336

Change-Id: I153af3111b835ce3bbfb56b9d91cf43269285ee4
parents c4a3e6d2 f45966f3
Loading
Loading
Loading
Loading
+32 −10
Original line number Diff line number Diff line
@@ -1756,7 +1756,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
						ctx.PropertyErrorf("systemserverclasspath_fragments", "%q is not a systemserverclasspath_fragment module", depName)
						return false
					}
					filesInfo = append(filesInfo, apexClasspathFragmentProtoFile(ctx, child))
					if af := apexClasspathFragmentProtoFile(ctx, child); af != nil {
						filesInfo = append(filesInfo, *af)
					}
					return true
				}
			case javaLibTag:
@@ -2159,17 +2161,23 @@ func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.
	}

	// Add classpaths.proto config.
	filesToAdd = append(filesToAdd, apexClasspathFragmentProtoFile(ctx, module))
	if af := apexClasspathFragmentProtoFile(ctx, module); af != nil {
		filesToAdd = append(filesToAdd, *af)
	}

	return filesToAdd
}

// apexClasspathFragmentProtoFile returns apexFile structure defining the classpath.proto config that
// the module contributes to the apex.
func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) apexFile {
	fragmentInfo := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
	classpathProtoOutput := fragmentInfo.ClasspathFragmentProtoOutput
	return newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), fragmentInfo.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
// the module contributes to the apex; or nil if the proto config was not generated.
func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile {
	info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
	if !info.ClasspathFragmentProtoGenerated {
		return nil
	}
	classpathProtoOutput := info.ClasspathFragmentProtoOutput
	af := newApexFile(ctx, classpathProtoOutput, classpathProtoOutput.Base(), info.ClasspathFragmentProtoInstallDir.Rel(), etc, nil)
	return &af
}

// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
@@ -2355,16 +2363,30 @@ func (a *apexBundle) checkStaticLinkingToStubLibraries(ctx android.ModuleContext
	})
}

// Enforce that Java deps of the apex are using stable SDKs to compile
// checkUpdatable enforces APEX and its transitive dep properties to have desired values for updatable APEXes.
func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
	if a.Updatable() {
		if String(a.properties.Min_sdk_version) == "" {
			ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
		}
		a.checkJavaStableSdkVersion(ctx)
		a.checkClasspathFragments(ctx)
	}
}

// checkClasspathFragments enforces that all classpath fragments in deps generate classpaths.proto config.
func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
	ctx.VisitDirectDeps(func(module android.Module) {
		if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
			info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
			if !info.ClasspathFragmentProtoGenerated {
				ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName())
			}
		}
	})
}

// checkJavaStableSdkVersion enforces that all Java deps are using stable SDKs to compile.
func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
	// Visit direct deps only. As long as we guarantee top-level deps are using stable SDKs,
	// java's checkLinkType guarantees correct usage for transitive deps
@@ -2383,7 +2405,7 @@ func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
	})
}

// Ensures that the all the dependencies are marked as available for this APEX
// checkApexAvailability ensures that the all the dependencies are marked as available for this APEX.
func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
	// Let's be practical. Availability for test, host, and the VNDK apex isn't important
	if ctx.Host() || a.testApex || a.vndkApex {
+41 −0
Original line number Diff line number Diff line
@@ -6700,6 +6700,47 @@ func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) {
	`)
}

func TestUpdatable_should_not_set_generate_classpaths_proto(t *testing.T) {
	testApexError(t, `"mysystemserverclasspathfragment" .* it must not set generate_classpaths_proto to false`, `
		apex {
			name: "myapex",
			key: "myapex.key",
			systemserverclasspath_fragments: [
				"mysystemserverclasspathfragment",
			],
			min_sdk_version: "29",
			updatable: true,
		}

		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		java_library {
			name: "foo",
			srcs: ["b.java"],
			min_sdk_version: "29",
			installable: true,
			apex_available: [
				"myapex",
			],
		}

		systemserverclasspath_fragment {
			name: "mysystemserverclasspathfragment",
			generate_classpaths_proto: false,
			contents: [
				"foo",
			],
			apex_available: [
				"myapex",
			],
		}
	`)
}

func TestNoUpdatableJarsInBootImage(t *testing.T) {
	// Set the BootJars in dexpreopt.GlobalConfig and productVariables to the same value. This can
	// result in an invalid configuration as it does not set the ArtApexJars and allows art apex
+51 −0
Original line number Diff line number Diff line
@@ -76,3 +76,54 @@ func TestSystemserverclasspathFragmentContents(t *testing.T) {
		`mysystemserverclasspathfragment`,
	})
}

func TestSystemserverclasspathFragmentNoGeneratedProto(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForTestWithSystemserverclasspathFragment,
		prepareForTestWithMyapex,
	).RunTestWithBp(t, `
		apex {
			name: "myapex",
			key: "myapex.key",
			systemserverclasspath_fragments: [
				"mysystemserverclasspathfragment",
			],
			updatable: false,
		}

		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		java_library {
			name: "foo",
			srcs: ["b.java"],
			installable: true,
			apex_available: [
				"myapex",
			],
		}

		systemserverclasspath_fragment {
			name: "mysystemserverclasspathfragment",
			generate_classpaths_proto: false,
			contents: [
				"foo",
			],
			apex_available: [
				"myapex",
			],
		}
	`)

	ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
		"javalib/foo.jar",
	})

	java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
		`myapex.key`,
		`mysystemserverclasspathfragment`,
	})
}
+29 −16
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package java
import (
	"fmt"
	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
	"strings"

	"android/soong/android"
@@ -44,6 +45,11 @@ func (c classpathType) String() string {
}

type classpathFragmentProperties struct {
	// Whether to generated classpaths.proto config instance for the fragment. If the config is not
	// generated, then relevant boot jars are added to platform classpath, i.e. platform_bootclasspath
	// or platform_systemserverclasspath. This is useful for non-updatable APEX boot jars, to keep
	// them as part of dexopt on device. Defaults to true.
	Generate_classpaths_proto *bool
}

// classpathFragment interface is implemented by a module that contributes jars to a *CLASSPATH
@@ -101,6 +107,8 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
}

func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.ModuleContext, jars []classpathJar) {
	generateProto := proptools.BoolDefault(c.properties.Generate_classpaths_proto, true)
	if generateProto {
		outputFilename := strings.ToLower(c.classpathType.String()) + ".pb"
		c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
		c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
@@ -117,8 +125,10 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
			FlagWithOutput("--output=", c.outputFilepath)

		rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
	}

	classpathProtoInfo := ClasspathFragmentProtoContentInfo{
		ClasspathFragmentProtoGenerated:  generateProto,
		ClasspathFragmentProtoInstallDir: c.installDirPath,
		ClasspathFragmentProtoOutput:     c.outputFilepath,
	}
@@ -164,6 +174,9 @@ func (c *ClasspathFragmentBase) androidMkEntries() []android.AndroidMkEntries {
var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{})

type ClasspathFragmentProtoContentInfo struct {
	// Whether the classpaths.proto config is generated for the fragment.
	ClasspathFragmentProtoGenerated bool

	// ClasspathFragmentProtoOutput is an output path for the generated classpaths.proto config of this module.
	//
	// The file should be copied to a relevant place on device, see ClasspathFragmentProtoInstallDir