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

Commit f45966f3 authored by satayev's avatar satayev Committed by Gerrit Code Review
Browse files

Merge "Add classpath fragment property to skip proto generation."

parents 5466a369 b98371cc
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