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

Commit 41f9b734 authored by Sam Delmerico's avatar Sam Delmerico Committed by Gerrit Code Review
Browse files

Merge "transitive Java deps for r8"

parents 7c30b6ba 9f9c0a22
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -651,6 +651,8 @@ type AARImport struct {
	// Functionality common to Module and Import.
	embeddableInModuleAndImport

	providesTransitiveHeaderJars

	properties AARImportProperties

	classpathFile         android.WritablePath
@@ -897,8 +899,11 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
		a.assetsPackage = mergedAssets
	}

	a.collectTransitiveHeaderJars(ctx)
	ctx.SetProvider(JavaInfoProvider, JavaInfo{
		HeaderJars:                     android.PathsIfNonNil(a.classpathFile),
		TransitiveLibsHeaderJars:       a.transitiveLibsHeaderJars,
		TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
		ImplementationAndResourcesJars: android.PathsIfNonNil(a.classpathFile),
		ImplementationJars:             android.PathsIfNonNil(a.classpathFile),
	})
+3 −0
Original line number Diff line number Diff line
@@ -1312,6 +1312,9 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo
			ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
			ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
		}
	} else {
		ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
		ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
	}
}

+49 −0
Original line number Diff line number Diff line
@@ -1583,6 +1583,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {

	ctx.SetProvider(JavaInfoProvider, JavaInfo{
		HeaderJars:                     android.PathsIfNonNil(j.headerJarFile),
		TransitiveLibsHeaderJars:       j.transitiveLibsHeaderJars,
		TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
		ImplementationAndResourcesJars: android.PathsIfNonNil(j.implementationAndResourcesJar),
		ImplementationJars:             android.PathsIfNonNil(j.implementationJarFile),
		ResourceJars:                   android.PathsIfNonNil(j.resourceJar),
@@ -1719,6 +1721,52 @@ func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
	return instrumentedJar
}

type providesTransitiveHeaderJars struct {
	// set of header jars for all transitive libs deps
	transitiveLibsHeaderJars *android.DepSet
	// set of header jars for all transitive static libs deps
	transitiveStaticLibsHeaderJars *android.DepSet
}

func (j *providesTransitiveHeaderJars) TransitiveLibsHeaderJars() *android.DepSet {
	return j.transitiveLibsHeaderJars
}

func (j *providesTransitiveHeaderJars) TransitiveStaticLibsHeaderJars() *android.DepSet {
	return j.transitiveStaticLibsHeaderJars
}

func (j *providesTransitiveHeaderJars) collectTransitiveHeaderJars(ctx android.ModuleContext) {
	directLibs := android.Paths{}
	directStaticLibs := android.Paths{}
	transitiveLibs := []*android.DepSet{}
	transitiveStaticLibs := []*android.DepSet{}
	ctx.VisitDirectDeps(func(module android.Module) {
		// don't add deps of the prebuilt version of the same library
		if ctx.ModuleName() == android.RemoveOptionalPrebuiltPrefix(module.Name()) {
			return
		}

		dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
		if dep.TransitiveLibsHeaderJars != nil {
			transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
		}
		if dep.TransitiveStaticLibsHeaderJars != nil {
			transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
		}

		tag := ctx.OtherModuleDependencyTag(module)
		_, isUsesLibDep := tag.(usesLibraryDependencyTag)
		if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
			directLibs = append(directLibs, dep.HeaderJars...)
		} else if tag == staticLibTag {
			directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
		}
	})
	j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
	j.transitiveStaticLibsHeaderJars = android.NewDepSet(android.POSTORDER, directStaticLibs, transitiveStaticLibs)
}

func (j *Module) HeaderJars() android.Paths {
	if j.headerJarFile == nil {
		return nil
@@ -1947,6 +1995,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {

	sdkLinkType, _ := j.getSdkLinkType(ctx, ctx.ModuleName())

	j.collectTransitiveHeaderJars(ctx)
	ctx.VisitDirectDeps(func(module android.Module) {
		otherName := ctx.OtherModuleName(module)
		tag := ctx.OtherModuleDependencyTag(module)
+31 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import (
	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/java/config"
	"android/soong/remoteexec"
)

@@ -90,6 +91,8 @@ type dexer struct {
	extraProguardFlagFiles android.Paths
	proguardDictionary     android.OptionalPath
	proguardUsageZip       android.OptionalPath

	providesTransitiveHeaderJars
}

func (d *dexer) effectiveOptimizeEnabled() bool {
@@ -249,12 +252,37 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
	})

	r8Flags = append(r8Flags, proguardRaiseDeps.FormJavaClassPath("-libraryjars"))
	r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
	r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))

	r8Deps = append(r8Deps, proguardRaiseDeps...)
	r8Flags = append(r8Flags, flags.bootClasspath.FormJavaClassPath("-libraryjars"))
	r8Deps = append(r8Deps, flags.bootClasspath...)
	r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars"))
	r8Deps = append(r8Deps, flags.dexClasspath...)
	r8Flags = append(r8Flags, flags.processorPath.FormJavaClassPath("-libraryjars"))
	r8Deps = append(r8Deps, flags.processorPath...)

	errorProneClasspath := classpath(android.PathsForSource(ctx, config.ErrorProneClasspath))
	r8Flags = append(r8Flags, errorProneClasspath.FormJavaClassPath("-libraryjars"))
	r8Deps = append(r8Deps, errorProneClasspath...)

	transitiveStaticLibsLookupMap := map[android.Path]bool{}
	if d.transitiveStaticLibsHeaderJars != nil {
		for _, jar := range d.transitiveStaticLibsHeaderJars.ToList() {
			transitiveStaticLibsLookupMap[jar] = true
		}
	}
	transitiveHeaderJars := android.Paths{}
	if d.transitiveLibsHeaderJars != nil {
		for _, jar := range d.transitiveLibsHeaderJars.ToList() {
			if _, ok := transitiveStaticLibsLookupMap[jar]; ok {
				// don't include a lib if it is already packaged in the current JAR as a static lib
				continue
			}
			transitiveHeaderJars = append(transitiveHeaderJars, jar)
		}
	}
	transitiveClasspath := classpath(transitiveHeaderJars)
	r8Flags = append(r8Flags, transitiveClasspath.FormJavaClassPath("-libraryjars"))
	r8Deps = append(r8Deps, transitiveClasspath...)

	flagFiles := android.Paths{
		android.PathForSource(ctx, "build/make/core/proguard.flags"),
+171 −1
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ import (
	"testing"

	"android/soong/android"

	"github.com/google/blueprint/proptools"
)

func TestR8(t *testing.T) {
@@ -74,7 +76,7 @@ func TestR8(t *testing.T) {

	android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
		appR8.Args["r8Flags"], libHeader.String())
	android.AssertStringDoesNotContain(t, "expected no  static_lib header jar in app javac classpath",
	android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
		appR8.Args["r8Flags"], staticLibHeader.String())
	android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
		appR8.Args["r8Flags"], "-ignorewarnings")
@@ -86,6 +88,174 @@ func TestR8(t *testing.T) {
		corePlatformAppR8.Args["r8Flags"], "--android-platform-build")
}

func TestR8TransitiveDeps(t *testing.T) {
	bp := `
		override_android_app {
			name: "override_app",
			base: "app",
		}

		android_app {
			name: "app",
			srcs: ["foo.java"],
			libs: [
				"lib",
				"uses_libs_dep_import",
			],
			static_libs: [
				"static_lib",
				"repeated_dep",
			],
			platform_apis: true,
		}

		java_library {
			name: "static_lib",
			srcs: ["foo.java"],
		}

		java_library {
			name: "lib",
			libs: [
				"transitive_lib",
				"repeated_dep",
				"prebuilt_lib",
			],
			static_libs: ["transitive_static_lib"],
			srcs: ["foo.java"],
		}

		java_library {
			name: "repeated_dep",
			srcs: ["foo.java"],
		}

		java_library {
			name: "transitive_static_lib",
			srcs: ["foo.java"],
		}

		java_library {
			name: "transitive_lib",
			srcs: ["foo.java"],
			libs: ["transitive_lib_2"],
		}

		java_library {
			name: "transitive_lib_2",
			srcs: ["foo.java"],
		}

		java_import {
			name: "lib",
			jars: ["lib.jar"],
		}

		java_library {
			name: "uses_lib",
			srcs: ["foo.java"],
		}

		java_library {
			name: "optional_uses_lib",
			srcs: ["foo.java"],
		}

		android_library {
			name: "uses_libs_dep",
			uses_libs: ["uses_lib"],
			optional_uses_libs: ["optional_uses_lib"],
		}

		android_library_import {
			name: "uses_libs_dep_import",
			aars: ["aar.aar"],
			static_libs: ["uses_libs_dep"],
		}
	`

	testcases := []struct {
		name      string
		unbundled bool
	}{
		{
			name:      "non-unbundled build",
			unbundled: false,
		},
		{
			name:      "unbundled build",
			unbundled: true,
		},
	}

	for _, tc := range testcases {
		t.Run(tc.name, func(t *testing.T) {
			fixturePreparer := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd
			if tc.unbundled {
				fixturePreparer = android.GroupFixturePreparers(
					fixturePreparer,
					android.FixtureModifyProductVariables(
						func(variables android.FixtureProductVariables) {
							variables.Unbundled_build = proptools.BoolPtr(true)
						},
					),
				)
			}
			result := fixturePreparer.RunTestWithBp(t, bp)

			getHeaderJar := func(name string) android.Path {
				mod := result.ModuleForTests(name, "android_common")
				return mod.Output("turbine-combined/" + name + ".jar").Output
			}

			appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
			overrideAppR8 := result.ModuleForTests("app", "android_common_override_app").Rule("r8")
			appHeader := getHeaderJar("app")
			overrideAppHeader := result.ModuleForTests("app", "android_common_override_app").Output("turbine-combined/app.jar").Output
			libHeader := getHeaderJar("lib")
			transitiveLibHeader := getHeaderJar("transitive_lib")
			transitiveLib2Header := getHeaderJar("transitive_lib_2")
			staticLibHeader := getHeaderJar("static_lib")
			transitiveStaticLibHeader := getHeaderJar("transitive_static_lib")
			repeatedDepHeader := getHeaderJar("repeated_dep")
			usesLibHeader := getHeaderJar("uses_lib")
			optionalUsesLibHeader := getHeaderJar("optional_uses_lib")
			prebuiltLibHeader := result.ModuleForTests("prebuilt_lib", "android_common").Output("combined/lib.jar").Output

			for _, rule := range []android.TestingBuildParams{appR8, overrideAppR8} {
				android.AssertStringDoesNotContain(t, "expected no app header jar in app r8 classpath",
					rule.Args["r8Flags"], appHeader.String())
				android.AssertStringDoesNotContain(t, "expected no override_app header jar in app r8 classpath",
					rule.Args["r8Flags"], overrideAppHeader.String())
				android.AssertStringDoesContain(t, "expected transitive lib header jar in app r8 classpath",
					rule.Args["r8Flags"], transitiveLibHeader.String())
				android.AssertStringDoesContain(t, "expected transitive lib ^2 header jar in app r8 classpath",
					rule.Args["r8Flags"], transitiveLib2Header.String())
				android.AssertStringDoesContain(t, "expected lib header jar in app r8 classpath",
					rule.Args["r8Flags"], libHeader.String())
				android.AssertStringDoesContain(t, "expected uses_lib header jar in app r8 classpath",
					rule.Args["r8Flags"], usesLibHeader.String())
				android.AssertStringDoesContain(t, "expected optional_uses_lib header jar in app r8 classpath",
					rule.Args["r8Flags"], optionalUsesLibHeader.String())
				android.AssertStringDoesNotContain(t, "expected no static_lib header jar in app r8 classpath",
					rule.Args["r8Flags"], staticLibHeader.String())
				android.AssertStringDoesNotContain(t, "expected no transitive static_lib header jar in app r8 classpath",
					rule.Args["r8Flags"], transitiveStaticLibHeader.String())
				// we shouldn't list this dep because it is already included as static_libs in the app
				android.AssertStringDoesNotContain(t, "expected no repeated_dep header jar in app r8 classpath",
					rule.Args["r8Flags"], repeatedDepHeader.String())
				// skip a prebuilt transitive dep if the source is also a transitive dep
				android.AssertStringDoesNotContain(t, "expected no prebuilt header jar in app r8 classpath",
					rule.Args["r8Flags"], prebuiltLibHeader.String())
				android.AssertStringDoesContain(t, "expected -ignorewarnings in app r8 flags",
					rule.Args["r8Flags"], "-ignorewarnings")
				android.AssertStringDoesContain(t, "expected --android-platform-build in app r8 flags",
					rule.Args["r8Flags"], "--android-platform-build")
			}
		})
	}
}

func TestR8Flags(t *testing.T) {
	result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, `
		android_app {
Loading