Make java binaries common instead of common-first
Previously, java binaries had both common and the first arch variants.
This was origionally added in aosp/556843. The reasoning there was so
that a java binary could be used as the dependency of a genrule.
However, now with transition mutators, we can make the incoming
transition redirect the arch variant to the common variant if the module
only has a common variant. This allows genrules to depend on the common
arch variant easily. That change is also included in this cl.
Bug: 372091092
Test: m nothing --no-skip-soong-tests
Change-Id: Iea612d050bff608d661f81566884653239015213
diff --git a/java/androidmk.go b/java/androidmk.go
index 2dff6cd..bacd925 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -281,50 +281,24 @@
return nil
}
- if !binary.isWrapperVariant {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(binary.outputFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
- entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
- if binary.dexJarFile.IsSet() {
- entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile.Path())
- }
- if len(binary.dexpreopter.builtInstalled) > 0 {
- entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
- }
- },
+ return []android.AndroidMkEntries{{
+ Class: "JAVA_LIBRARIES",
+ OutputFile: android.OptionalPathForPath(binary.outputFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetPath("LOCAL_SOONG_HEADER_JAR", binary.headerJarFile)
+ entries.SetPath("LOCAL_SOONG_CLASSES_JAR", binary.implementationAndResourcesJar)
+ if binary.dexJarFile.IsSet() {
+ entries.SetPath("LOCAL_SOONG_DEX_JAR", binary.dexJarFile.Path())
+ }
+ if len(binary.dexpreopter.builtInstalled) > 0 {
+ entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
+ }
+ entries.AddStrings("LOCAL_REQUIRED_MODULES", binary.androidMkNamesOfJniLibs...)
},
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- fmt.Fprintln(w, "jar_installed_module := $(LOCAL_INSTALLED_MODULE)")
- },
- },
- }}
- } else {
- outputFile := binary.wrapperFile
-
- return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "EXECUTABLES",
- OutputFile: android.OptionalPathForPath(outputFile),
- ExtraEntries: []android.AndroidMkExtraEntriesFunc{
- func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.SetBool("LOCAL_STRIP_MODULE", false)
- entries.AddStrings("LOCAL_REQUIRED_MODULES", binary.androidMkNamesOfJniLibs...)
- },
- },
- ExtraFooters: []android.AndroidMkExtraFootersFunc{
- func(w io.Writer, name, prefix, moduleDir string) {
- // Ensure that the wrapper script timestamp is always updated when the jar is updated
- fmt.Fprintln(w, "$(LOCAL_INSTALLED_MODULE): $(jar_installed_module)")
- fmt.Fprintln(w, "jar_installed_module :=")
- },
- },
- }}
- }
+ },
+ }}
}
func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/java/java.go b/java/java.go
index 018850f..d972887 100644
--- a/java/java.go
+++ b/java/java.go
@@ -450,7 +450,6 @@
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
jniInstallTag = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
- binaryInstallTag = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
@@ -1004,13 +1003,7 @@
}
j.compile(ctx, nil, nil, nil, nil)
- // If this module is an impl library created from java_sdk_library,
- // install the files under the java_sdk_library module outdir instead of this module outdir.
- if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
- j.setInstallRules(ctx, proptools.String(j.SdkLibraryName()))
- } else {
- j.setInstallRules(ctx, ctx.ModuleName())
- }
+ j.setInstallRules(ctx)
android.SetProvider(ctx, android.TestOnlyProviderKey, android.TestModuleInformation{
TestOnly: Bool(j.sourceProperties.Test_only),
@@ -1020,7 +1013,27 @@
setOutputFiles(ctx, j.Module)
}
-func (j *Library) setInstallRules(ctx android.ModuleContext, installModuleName string) {
+func (j *Library) getJarInstallDir(ctx android.ModuleContext) android.InstallPath {
+ var installDir android.InstallPath
+ if ctx.InstallInTestcases() {
+ var archDir string
+ if !ctx.Host() {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ installModuleName := ctx.ModuleName()
+ // If this module is an impl library created from java_sdk_library,
+ // install the files under the java_sdk_library module outdir instead of this module outdir.
+ if j.SdkLibraryName() != nil && strings.HasSuffix(j.Name(), ".impl") {
+ installModuleName = proptools.String(j.SdkLibraryName())
+ }
+ installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ }
+ return installDir
+}
+
+func (j *Library) setInstallRules(ctx android.ModuleContext) {
apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if (Bool(j.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
@@ -1034,17 +1047,7 @@
android.PathForHostDexInstall(ctx, "framework"),
j.Stem()+"-hostdex.jar", j.outputFile)
}
- var installDir android.InstallPath
- if ctx.InstallInTestcases() {
- var archDir string
- if !ctx.Host() {
- archDir = ctx.DeviceConfig().DeviceArch()
- }
- installDir = android.PathForModuleInstall(ctx, installModuleName, archDir)
- } else {
- installDir = android.PathForModuleInstall(ctx, "framework")
- }
- j.installFile = ctx.InstallFileWithoutCheckbuild(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
+ j.installFile = ctx.InstallFileWithoutCheckbuild(j.getJarInstallDir(ctx), j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
}
@@ -1804,8 +1807,6 @@
binaryProperties binaryProperties
- isWrapperVariant bool
-
wrapperFile android.Path
binaryFile android.InstallPath
@@ -1819,97 +1820,94 @@
func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.stem = proptools.StringDefault(j.overridableProperties.Stem, ctx.ModuleName())
- if ctx.Arch().ArchType == android.Common {
- // Compile the jar
- if j.binaryProperties.Main_class != nil {
- if j.properties.Manifest != nil {
- ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
- }
- manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
- GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
- j.overrideManifest = android.OptionalPathForPath(manifestFile)
- }
-
- j.Library.GenerateAndroidBuildActions(ctx)
+ // Handle the binary wrapper. This comes before compiling the jar so that the wrapper
+ // is the first PackagingSpec
+ if j.binaryProperties.Wrapper != nil {
+ j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
} else {
- // Handle the binary wrapper
- j.isWrapperVariant = true
-
- if j.binaryProperties.Wrapper != nil {
- j.wrapperFile = android.PathForModuleSrc(ctx, *j.binaryProperties.Wrapper)
- } else {
- if ctx.Windows() {
- ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
- }
-
- if ctx.Device() {
- // device binary should have a main_class property if it does not
- // have a specific wrapper, so that a default wrapper can
- // be generated for it.
- if j.binaryProperties.Main_class == nil {
- ctx.PropertyErrorf("main_class", "main_class property "+
- "is required for device binary if no default wrapper is assigned")
- } else {
- wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
- jarName := j.Stem() + ".jar"
- partition := j.PartitionTag(ctx.DeviceConfig())
- ctx.Build(pctx, android.BuildParams{
- Rule: deviceBinaryWrapper,
- Output: wrapper,
- Args: map[string]string{
- "jar_name": jarName,
- "partition": partition,
- "main_class": String(j.binaryProperties.Main_class),
- },
- })
- j.wrapperFile = wrapper
- }
- } else {
- j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
- }
- }
-
- ext := ""
if ctx.Windows() {
- ext = ".bat"
+ ctx.PropertyErrorf("wrapper", "wrapper is required for Windows")
}
- // The host installation rules make the installed wrapper depend on all the dependencies
- // of the wrapper variant, which will include the common variant's jar file and any JNI
- // libraries. This is verified by TestBinary.
- j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
- ctx.ModuleName()+ext, j.wrapperFile)
-
- setOutputFiles(ctx, j.Library.Module)
-
- // Set the jniLibs of this binary.
- // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
- // install these alongside the java binary.
- ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
- // Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
- bmn, _ := jni.(interface{ BaseModuleName() string })
- j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
- })
- // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
- ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
- if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
- ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
+ if ctx.Device() {
+ // device binary should have a main_class property if it does not
+ // have a specific wrapper, so that a default wrapper can
+ // be generated for it.
+ if j.binaryProperties.Main_class == nil {
+ ctx.PropertyErrorf("main_class", "main_class property "+
+ "is required for device binary if no default wrapper is assigned")
+ } else {
+ wrapper := android.PathForModuleOut(ctx, ctx.ModuleName()+".sh")
+ jarName := j.Stem() + ".jar"
+ partition := j.PartitionTag(ctx.DeviceConfig())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: deviceBinaryWrapper,
+ Output: wrapper,
+ Args: map[string]string{
+ "jar_name": jarName,
+ "partition": partition,
+ "main_class": String(j.binaryProperties.Main_class),
+ },
+ })
+ j.wrapperFile = wrapper
}
- })
+ } else {
+ j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh")
+ }
}
+
+ ext := ""
+ if ctx.Windows() {
+ ext = ".bat"
+ }
+
+ // The host installation rules make the installed wrapper depend on all the dependencies
+ // of the wrapper variant, which will include the common variant's jar file and any JNI
+ // libraries. This is verified by TestBinary. Also make it depend on the jar file so that
+ // the binary file timestamp will update when the jar file timestamp does. The jar file is
+ // built later on, in j.Library.GenerateAndroidBuildActions, so we have to create an identical
+ // installpath representing it here.
+ j.binaryFile = ctx.InstallExecutable(android.PathForModuleInstall(ctx, "bin"),
+ ctx.ModuleName()+ext, j.wrapperFile, j.getJarInstallDir(ctx).Join(ctx, j.Stem()+".jar"))
+
+ // Set the jniLibs of this binary.
+ // These will be added to `LOCAL_REQUIRED_MODULES`, and the kati packaging system will
+ // install these alongside the java binary.
+ ctx.VisitDirectDepsWithTag(jniInstallTag, func(jni android.Module) {
+ // Use the BaseModuleName of the dependency (without any prebuilt_ prefix)
+ bmn, _ := jni.(interface{ BaseModuleName() string })
+ j.androidMkNamesOfJniLibs = append(j.androidMkNamesOfJniLibs, bmn.BaseModuleName()+":"+jni.Target().Arch.ArchType.Bitness())
+ })
+ // Check that native libraries are not listed in `required`. Prompt users to use `jni_libs` instead.
+ ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
+ if _, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider); hasSharedLibraryInfo {
+ ctx.ModuleErrorf("cc_library %s is no longer supported in `required` of java_binary modules. Please use jni_libs instead.", dep.Name())
+ }
+ })
+
+ // Compile the jar
+ if j.binaryProperties.Main_class != nil {
+ if j.properties.Manifest != nil {
+ ctx.PropertyErrorf("main_class", "main_class cannot be used when manifest is set")
+ }
+ manifestFile := android.PathForModuleOut(ctx, "manifest.txt")
+ GenerateMainClassManifest(ctx, manifestFile, String(j.binaryProperties.Main_class))
+ j.overrideManifest = android.OptionalPathForPath(manifestFile)
+ }
+
+ j.Library.GenerateAndroidBuildActions(ctx)
}
func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) {
- if ctx.Arch().ArchType == android.Common {
- j.deps(ctx)
- }
+ j.deps(ctx)
// These dependencies ensure the installation rules will install the jar file when the
// wrapper is installed, and the jni libraries when the wrapper is installed.
- if ctx.Arch().ArchType != android.Common {
- ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...)
- ctx.AddVariationDependencies(
- []blueprint.Variation{{Mutator: "arch", Variation: android.CommonArch.String()}},
- binaryInstallTag, ctx.ModuleName())
+ if ctx.Os().Class == android.Host {
+ ctx.AddVariationDependencies(ctx.Config().BuildOSTarget.Variations(), jniInstallTag, j.binaryProperties.Jni_libs...)
+ } else if ctx.Os().Class == android.Device {
+ ctx.AddVariationDependencies(ctx.Config().AndroidFirstDeviceTarget.Variations(), jniInstallTag, j.binaryProperties.Jni_libs...)
+ } else {
+ ctx.ModuleErrorf("Unknown os class")
}
}
@@ -1929,7 +1927,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
- android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
+ android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
@@ -1947,7 +1945,7 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
- android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
+ android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
return module
}
diff --git a/java/java_test.go b/java/java_test.go
index 24dabdb..51cfdab 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -569,8 +569,7 @@
bar := ctx.ModuleForTests("bar", buildOS+"_common")
barJar := bar.Output("bar.jar").Output.String()
- barWrapper := ctx.ModuleForTests("bar", buildOS+"_x86_64")
- barWrapperDeps := barWrapper.Output("bar").Implicits.Strings()
+ barWrapperDeps := bar.Output("bar").Implicits.Strings()
libjni := ctx.ModuleForTests("libjni", buildOS+"_x86_64_shared")
libjniSO := libjni.Rule("Cp").Output.String()
@@ -1931,7 +1930,7 @@
main_class: "foo.bar.jb",
}
`)
- wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_arm64_armv8-a").AllOutputs())
+ wrapperPath := fmt.Sprint(ctx.ModuleForTests("foo", "android_common").AllOutputs())
if !strings.Contains(wrapperPath, "foo.sh") {
t.Errorf("wrapper file foo.sh is not generated")
}
@@ -3125,13 +3124,6 @@
}
`
res, _ := testJava(t, bp)
- // The first variant installs the native library via the common variant, so check the deps of both variants.
- nativeVariantDepsWithDups := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_arm64_armv8-a").Module(), "mynativelib")
- nativeVariantDepsWithDups = append(nativeVariantDepsWithDups, findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")...)
-
- nativeVariantDepsUnique := map[blueprint.Module]bool{}
- for _, dep := range nativeVariantDepsWithDups {
- nativeVariantDepsUnique[dep] = true
- }
- android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(nativeVariantDepsUnique))
+ deps := findDepsOfModule(res, res.ModuleForTests("myjavabin", "android_common").Module(), "mynativelib")
+ android.AssertIntEquals(t, "Create a dep on the first variant", 1, len(deps))
}