diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/aar.go | 28 | ||||
| -rw-r--r-- | java/android_manifest.go | 3 | ||||
| -rwxr-xr-x | java/app.go | 9 | ||||
| -rw-r--r-- | java/app_import.go | 53 | ||||
| -rw-r--r-- | java/app_import_test.go | 27 | ||||
| -rw-r--r-- | java/app_test.go | 3 | ||||
| -rw-r--r-- | java/base.go | 49 | ||||
| -rw-r--r-- | java/config/config.go | 2 | ||||
| -rw-r--r-- | java/core-libraries/Android.bp | 25 | ||||
| -rw-r--r-- | java/dex.go | 38 | ||||
| -rw-r--r-- | java/dex_test.go | 172 | ||||
| -rw-r--r-- | java/droidstubs.go | 26 | ||||
| -rw-r--r-- | java/droidstubs_test.go | 24 | ||||
| -rw-r--r-- | java/java.go | 145 | ||||
| -rw-r--r-- | java/java_test.go | 198 | ||||
| -rw-r--r-- | java/kotlin_test.go | 14 | ||||
| -rw-r--r-- | java/sdk_library.go | 2 |
17 files changed, 693 insertions, 125 deletions
diff --git a/java/aar.go b/java/aar.go index f4a2ff287..a483e13b9 100644 --- a/java/aar.go +++ b/java/aar.go @@ -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), }) @@ -1031,7 +1036,7 @@ func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "aar_import", - Bzl_load_location: "@rules_android//rules:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:rules.bzl", }, android.CommonAttributes{Name: name}, &bazelAndroidLibraryImport{ @@ -1041,6 +1046,21 @@ func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) { }, ) + neverlink := true + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "android_library", + Bzl_load_location: "//build/bazel/rules/android:rules.bzl", + }, + android.CommonAttributes{Name: name + "-neverlink"}, + &bazelAndroidLibrary{ + javaLibraryAttributes: &javaLibraryAttributes{ + Neverlink: bazel.BoolAttribute{Value: &neverlink}, + Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}), + }, + }, + ) + } func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) { @@ -1054,10 +1074,14 @@ func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") } + if len(a.properties.Common_srcs) != 0 { + commonAttrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.properties.Common_srcs)) + } + name := a.Name() props := bazel.BazelTargetModuleProperties{ Rule_class: "android_library", - Bzl_load_location: "@rules_android//rules:rules.bzl", + Bzl_load_location: "//build/bazel/rules/android:rules.bzl", } ctx.CreateBazelTargetModule( diff --git a/java/android_manifest.go b/java/android_manifest.go index c7853103f..f6457a096 100644 --- a/java/android_manifest.go +++ b/java/android_manifest.go @@ -149,13 +149,14 @@ func ManifestFixer(ctx android.ModuleContext, manifest android.Path, if params.SdkContext != nil { targetSdkVersion := targetSdkVersionForManifestFixer(ctx, params) - args = append(args, "--targetSdkVersion ", targetSdkVersion) if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" { targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String()) deps = append(deps, ApiFingerprintPath(ctx)) } + args = append(args, "--targetSdkVersion ", targetSdkVersion) + minSdkVersion, err := params.SdkContext.MinSdkVersion(ctx).EffectiveVersionString(ctx) if err != nil { ctx.ModuleErrorf("invalid minSdkVersion: %s", err) diff --git a/java/app.go b/java/app.go index 3c5760b58..4d9c407c5 100755 --- a/java/app.go +++ b/java/app.go @@ -801,6 +801,8 @@ func collectAppDeps(ctx android.ModuleContext, app appDepsInterface, unstrippedFile: dep.UnstrippedOutputFile(), partition: dep.Partition(), }) + } else if ctx.Config().AllowMissingDependencies() { + ctx.AddMissingDependencies([]string{otherName}) } else { ctx.ModuleErrorf("dependency %q missing output file", otherName) } @@ -1310,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)...) } } @@ -1476,7 +1481,7 @@ func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *An props := bazel.BazelTargetModuleProperties{ Rule_class: "android_app_certificate", - Bzl_load_location: "//build/bazel/rules/android:android_app_certificate.bzl", + Bzl_load_location: "//build/bazel/rules/android:rules.bzl", } ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs) @@ -1515,7 +1520,7 @@ func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) { props := bazel.BazelTargetModuleProperties{ Rule_class: "android_binary", - Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl", + Bzl_load_location: "//build/bazel/rules/android:rules.bzl", } ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs) diff --git a/java/app_import.go b/java/app_import.go index 8c1e19c3e..e24e7804e 100644 --- a/java/app_import.go +++ b/java/app_import.go @@ -17,6 +17,7 @@ package java // This file contains the module implementations for android_app_import and android_test_import. import ( + "github.com/google/blueprint" "reflect" "github.com/google/blueprint/proptools" @@ -31,6 +32,24 @@ func init() { initAndroidAppImportVariantGroupTypes() } +var ( + uncompressEmbeddedJniLibsRule = pctx.AndroidStaticRule("uncompress-embedded-jni-libs", blueprint.RuleParams{ + Command: `if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` + + `${config.Zip2ZipCmd} -i $in -o $out -0 'lib/**/*.so'` + + `; else cp -f $in $out; fi`, + CommandDeps: []string{"${config.Zip2ZipCmd}"}, + Description: "Uncompress embedded JNI libs", + }) + + uncompressDexRule = pctx.AndroidStaticRule("uncompress-dex", blueprint.RuleParams{ + Command: `if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then ` + + `${config.Zip2ZipCmd} -i $in -o $out -0 'classes*.dex'` + + `; else cp -f $in $out; fi`, + CommandDeps: []string{"${config.Zip2ZipCmd}"}, + Description: "Uncompress dex files", + }) +) + func RegisterAppImportBuildComponents(ctx android.RegistrationContext) { ctx.RegisterModuleType("android_app_import", AndroidAppImportFactory) ctx.RegisterModuleType("android_test_import", AndroidTestImportFactory) @@ -193,15 +212,12 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( }) return } - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). - BuiltTool("zip2zip"). - FlagWithInput("-i ", inputPath). - FlagWithOutput("-o ", outputPath). - FlagWithArg("-0 ", "'lib/**/*.so'"). - Textf(`; else cp -f %s %s; fi`, inputPath, outputPath) - rule.Build("uncompress-embedded-jni-libs", "Uncompress embedded JIN libs") + + ctx.Build(pctx, android.BuildParams{ + Rule: uncompressEmbeddedJniLibsRule, + Input: inputPath, + Output: outputPath, + }) } // Returns whether this module should have the dex file stored uncompressed in the APK. @@ -218,19 +234,6 @@ func (a *AndroidAppImport) shouldUncompressDex(ctx android.ModuleContext) bool { return shouldUncompressDex(ctx, &a.dexpreopter) } -func (a *AndroidAppImport) uncompressDex( - ctx android.ModuleContext, inputPath android.Path, outputPath android.OutputPath) { - rule := android.NewRuleBuilder(pctx, ctx) - rule.Command(). - Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). - BuiltTool("zip2zip"). - FlagWithInput("-i ", inputPath). - FlagWithOutput("-o ", outputPath). - FlagWithArg("-0 ", "'classes*.dex'"). - Textf(`; else cp -f %s %s; fi`, inputPath, outputPath) - rule.Build("uncompress-dex", "Uncompress dex files") -} - func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.generateAndroidBuildActions(ctx) } @@ -306,7 +309,11 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext a.dexpreopter.dexpreopt(ctx, jnisUncompressed) if a.dexpreopter.uncompressedDex { dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk") - a.uncompressDex(ctx, jnisUncompressed, dexUncompressed.OutputPath) + ctx.Build(pctx, android.BuildParams{ + Rule: uncompressDexRule, + Input: jnisUncompressed, + Output: dexUncompressed, + }) jnisUncompressed = dexUncompressed } diff --git a/java/app_import_test.go b/java/app_import_test.go index ad27e3ae7..a29606f89 100644 --- a/java/app_import_test.go +++ b/java/app_import_test.go @@ -17,7 +17,6 @@ package java import ( "fmt" "reflect" - "regexp" "strings" "testing" @@ -294,7 +293,6 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { }, } - jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") for _, test := range testCases { result := android.GroupFixturePreparers( PrepareForTestWithJavaDefaultModules, @@ -305,13 +303,9 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { ).RunTestWithBp(t, bp) variant := result.ModuleForTests("foo", "android_common") - jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command - matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) - if len(matches) != 2 { - t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) - } - if strings.HasSuffix(matches[1], test.expected) { - t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) + input := variant.Output("jnis-uncompressed/foo.apk").Input.String() + if strings.HasSuffix(input, test.expected) { + t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input) } provenanceMetaDataRule := variant.Rule("genProvenanceMetaData") @@ -456,7 +450,6 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) { }, } - jniRuleRe := regexp.MustCompile("^if \\(zipinfo (\\S+)") for _, test := range testCases { ctx, _ := testJava(t, test.bp) @@ -469,13 +462,9 @@ func TestAndroidAppImport_ArchVariants(t *testing.T) { android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule) continue } - jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command - matches := jniRuleRe.FindStringSubmatch(jniRuleCommand) - if len(matches) != 2 { - t.Errorf("failed to extract the src apk path from %q", jniRuleCommand) - } - if strings.HasSuffix(matches[1], test.expected) { - t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1]) + input := variant.Output("jnis-uncompressed/foo.apk").Input.String() + if strings.HasSuffix(input, test.expected) { + t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input) } rule := variant.Rule("genProvenanceMetaData") android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String()) @@ -686,8 +675,8 @@ func TestAndroidTestImport_NoJinUncompressForPresigned(t *testing.T) { `) variant := ctx.ModuleForTests("foo", "android_common") - jniRule := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command - if !strings.HasPrefix(jniRule, "if (zipinfo") { + jniRule := variant.Output("jnis-uncompressed/foo.apk").BuildParams.Rule.String() + if jniRule == android.Cp.String() { t.Errorf("Unexpected JNI uncompress rule command: " + jniRule) } diff --git a/java/app_test.go b/java/app_test.go index cd8886426..3fb67c188 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -3163,6 +3163,7 @@ func TestDefaultAppTargetSdkVersionForUpdatableModules(t *testing.T) { variables.Platform_sdk_version = &platform_sdk_version variables.Platform_sdk_codename = &platform_sdk_codename variables.Platform_version_active_codenames = []string{platform_sdk_codename} + variables.Unbundled_build = proptools.BoolPtr(true) variables.Unbundled_build_apps = []string{"sampleModule"} }), ) @@ -3241,6 +3242,7 @@ func TestEnforceDefaultAppTargetSdkVersionFlag(t *testing.T) { variables.Platform_sdk_final = &testCase.platform_sdk_final variables.Platform_sdk_version = &platform_sdk_version variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build = proptools.BoolPtr(true) variables.Unbundled_build_apps = []string{"sampleModule"} }), ) @@ -3311,6 +3313,7 @@ func TestEnforceDefaultAppTargetSdkVersionFlagForTests(t *testing.T) { variables.Platform_sdk_final = &testCase.platform_sdk_final variables.Platform_sdk_version = &platform_sdk_version variables.Platform_sdk_codename = &platform_sdk_codename + variables.Unbundled_build = proptools.BoolPtr(true) variables.Unbundled_build_apps = []string{"sampleModule"} }), ) diff --git a/java/base.go b/java/base.go index 84fda37cb..cce06a4e9 100644 --- a/java/base.go +++ b/java/base.go @@ -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) diff --git a/java/config/config.go b/java/config/config.go index 49d88c4fd..7c22076ae 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -96,8 +96,6 @@ func init() { }, dexerJavaVmFlagsList...)) exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{ "-JXmx2048M", - // Disable this optimization as it can impact weak reference semantics. See b/233432839. - "-JDcom.android.tools.r8.disableEnqueuerDeferredTracing=true", }, dexerJavaVmFlagsList...)) exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{ diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp index 4fb1d76fd..b9332dda5 100644 --- a/java/core-libraries/Android.bp +++ b/java/core-libraries/Android.bp @@ -63,11 +63,6 @@ java_library { // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", - // This one is not on device but it's needed when javac compiles code - // containing @Generated annotations produced by some code generation - // tools. - // See http://b/123891440. - "core-generated-annotation-stubs", ], sdk_version: "none", system_modules: "none", @@ -148,11 +143,6 @@ java_library { // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", - // This one is not on device but it's needed when javac compiles code - // containing @Generated annotations produced by some code generation - // tools. - // See http://b/123891440. - "core-generated-annotation-stubs", ], sdk_version: "none", system_modules: "none", @@ -278,11 +268,6 @@ java_system_modules { // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", - // This one is not on device but it's needed when javac compiles code - // containing @Generated annotations produced by some code generation - // tools. - // See http://b/123891440. - "core-generated-annotation-stubs", ], } @@ -294,11 +279,6 @@ java_system_modules { // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", - // This one is not on device but it's needed when javac compiles code - // containing @Generated annotations produced by some code generation - // tools. - // See http://b/123891440. - "core-generated-annotation-stubs", ], } @@ -322,11 +302,6 @@ java_system_modules { // This one is not on device but it's needed when javac compiles code // containing lambdas. "core-lambda-stubs-for-system-modules", - // This one is not on device but it's needed when javac compiles code - // containing @Generated annotations produced by some code generation - // tools. - // See http://b/123891440. - "core-generated-annotation-stubs", // Ensure that core libraries that depend on the public API can access // the UnsupportedAppUsage, CorePlatformApi and IntraCoreApi diff --git a/java/dex.go b/java/dex.go index 40ee99d3b..a8dd37508 100644 --- a/java/dex.go +++ b/java/dex.go @@ -89,7 +89,10 @@ type dexer struct { // list of extra proguard flag files extraProguardFlagFiles android.Paths proguardDictionary android.OptionalPath + proguardConfiguration android.OptionalPath proguardUsageZip android.OptionalPath + + providesTransitiveHeaderJars } func (d *dexer) effectiveOptimizeEnabled() bool { @@ -130,17 +133,18 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8", var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + - `rm -f "$outDict" && rm -rf "${outUsageDir}" && ` + + `rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` + `mkdir -p $$(dirname ${outUsage}) && ` + `mkdir -p $$(dirname $tmpJar) && ` + `${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` + `$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` + `--no-data-resources ` + `-printmapping ${outDict} ` + + `--pg-conf-output ${outConfig} ` + `-printusage ${outUsage} ` + `--deps-file ${out}.d ` + `$r8Flags && ` + - `touch "${outDict}" "${outUsage}" && ` + + `touch "${outDict}" "${outConfig}" "${outUsage}" && ` + `${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` + `rm -rf ${outUsageDir} && ` + `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` + @@ -176,7 +180,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8", ExecStrategy: "${config.RER8ExecStrategy}", Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"}, }, - }, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir", + }, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir", "r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"}) func (d *dexer) dexCommonFlags(ctx android.ModuleContext, @@ -249,13 +253,32 @@ 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...) + 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"), } @@ -342,6 +365,8 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi if useR8 { proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary") d.proguardDictionary = android.OptionalPathForPath(proguardDictionary) + proguardConfiguration := android.PathForModuleOut(ctx, "proguard_configuration") + d.proguardConfiguration = android.OptionalPathForPath(proguardConfiguration) proguardUsageDir := android.PathForModuleOut(ctx, "proguard_usage") proguardUsage := proguardUsageDir.Join(ctx, ctx.Namespace().Path, android.ModuleNameWithPossibleOverride(ctx), "unused.txt") @@ -354,6 +379,7 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "), "zipFlags": zipFlags, "outDict": proguardDictionary.String(), + "outConfig": proguardConfiguration.String(), "outUsageDir": proguardUsageDir.String(), "outUsage": proguardUsage.String(), "outUsageZip": proguardUsageZip.String(), diff --git a/java/dex_test.go b/java/dex_test.go index fc6cd0f3f..dc85f9e34 100644 --- a/java/dex_test.go +++ b/java/dex_test.go @@ -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 { diff --git a/java/droidstubs.go b/java/droidstubs.go index 4bbe70ac4..d9613e536 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -148,6 +148,10 @@ type DroidstubsProperties struct { // path or filegroup to file defining extension an SDK name <-> numerical ID mapping and // what APIs exist in which SDKs; passed to metalava via --sdk-extensions-info Extensions_info_file *string `android:"path"` + + // API surface of this module. If set, the module contributes to an API surface. + // For the full list of available API surfaces, refer to soong/android/sdk_version.go + Api_surface *string } // Used by xsd_config @@ -178,6 +182,10 @@ func DroidstubsFactory() android.Module { &module.Javadoc.properties) InitDroiddocModule(module, android.HostAndDeviceSupported) + + module.SetDefaultableHook(func(ctx android.DefaultableHookContext) { + module.createApiContribution(ctx) + }) return module } @@ -862,6 +870,23 @@ func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) { }, attrs) } +func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) { + api_file := d.properties.Check_api.Current.Api_file + api_surface := d.properties.Api_surface + + props := struct { + Name *string + Api_surface *string + Api_file *string + }{} + + props.Name = proptools.StringPtr(d.Name() + ".api.contribution") + props.Api_surface = api_surface + props.Api_file = api_file + + ctx.CreateModule(ApiContributionFactory, &props) +} + // TODO (b/262014796): Export the API contributions of CorePlatformApi // A map to populate the api surface of a droidstub from a substring appearing in its name // This map assumes that droidstubs (either checked-in or created by java_sdk_library) @@ -876,6 +901,7 @@ var ( "system": android.SdkSystem, "module_lib": android.SdkModule, "module-lib": android.SdkModule, + "platform.api": android.SdkCorePlatform, "test": android.SdkTest, "toolchain": android.SdkToolchain, } diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index ef2e6dc8a..6c2293746 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -346,3 +346,27 @@ func TestApiSurfaceFromDroidStubsName(t *testing.T) { android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name)) } } + +func TestDroidStubsApiContributionGeneration(t *testing.T) { + ctx, _ := testJavaWithFS(t, ` + droidstubs { + name: "foo", + srcs: ["A/a.java"], + api_surface: "public", + check_api: { + current: { + api_file: "A/current.txt", + removed_api_file: "A/removed.txt", + } + } + } + `, + map[string][]byte{ + "A/a.java": nil, + "A/current.txt": nil, + "A/removed.txt": nil, + }, + ) + + ctx.ModuleForTests("foo.api.contribution", "") +} diff --git a/java/java.go b/java/java.go index 6e428cb1f..874f93576 100644 --- a/java/java.go +++ b/java/java.go @@ -230,6 +230,12 @@ type JavaInfo struct { // against this module. If empty, ImplementationJars should be used instead. HeaderJars android.Paths + // 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 + // ImplementationAndResourceJars is a list of jars that contain the implementations of classes // in the module as well as any resources included in the module. ImplementationAndResourcesJars android.Paths @@ -380,6 +386,7 @@ var ( instrumentationForTag = dependencyTag{name: "instrumentation_for"} extraLintCheckTag = dependencyTag{name: "extra-lint-check", toolchain: true} jniLibTag = dependencyTag{name: "jnilib", runtimeLinked: true} + r8LibraryJarTag = dependencyTag{name: "r8-libraryjar", runtimeLinked: true} syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} jniInstallTag = installDependencyTag{name: "jni install"} binaryInstallTag = installDependencyTag{name: "binary install"} @@ -1581,7 +1588,11 @@ type JavaApiImportInfo struct { var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{}) func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) { - apiFile := android.PathForModuleSrc(ctx, String(ap.properties.Api_file)) + var apiFile android.Path = nil + if apiFileString := ap.properties.Api_file; apiFileString != nil { + apiFile = android.PathForModuleSrc(ctx, String(apiFileString)) + } + ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{ ApiFile: apiFile, }) @@ -1612,13 +1623,17 @@ type JavaApiLibraryProperties struct { // List of flags to be passed to the javac compiler to generate jar file Javacflags []string + + // List of shared java libs that this module has dependencies to and + // should be passed as classpath in javac invocation + Libs []string } func ApiLibraryFactory() android.Module { module := &ApiLibrary{} android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon) - android.InitDefaultableModule(module) module.AddProperties(&module.properties) + android.InitDefaultableModule(module) return module } @@ -1683,6 +1698,7 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { for _, apiContributionName := range apiContributions { ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName) } + ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...) } func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1700,10 +1716,22 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { homeDir := android.PathForModuleOut(ctx, "metalava", "home") - var srcFiles []android.Path - ctx.VisitDirectDepsWithTag(javaApiContributionTag, func(dep android.Module) { - provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo) - srcFiles = append(srcFiles, android.PathForSource(ctx, provider.ApiFile.String())) + var srcFiles android.Paths + var classPaths android.Paths + ctx.VisitDirectDeps(func(dep android.Module) { + tag := ctx.OtherModuleDependencyTag(dep) + switch tag { + case javaApiContributionTag: + provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo) + providerApiFile := provider.ApiFile + if providerApiFile == nil { + ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name()) + } + srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String())) + case libTag: + provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) + classPaths = append(classPaths, provider.HeaderJars...) + } }) // Add the api_files inputs @@ -1733,11 +1761,16 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { var flags javaBuilderFlags flags.javaVersion = getStubsJavaVersion() flags.javacFlags = strings.Join(al.properties.Javacflags, " ") + flags.classpath = classpath(classPaths) TransformJavaToClasses(ctx, al.stubsJar, 0, android.Paths{}, android.Paths{al.stubsSrcJar}, flags, android.Paths{}) ctx.Phony(ctx.ModuleName(), al.stubsJar) + + ctx.SetProvider(JavaInfoProvider, JavaInfo{ + HeaderJars: android.PathsIfNonNil(al.stubsJar), + }) } // @@ -1920,9 +1953,9 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { var flags javaBuilderFlags + j.collectTransitiveHeaderJars(ctx) ctx.VisitDirectDeps(func(module android.Module) { tag := ctx.OtherModuleDependencyTag(module) - if ctx.OtherModuleHasProvider(module, JavaInfoProvider) { dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) switch tag { @@ -2012,6 +2045,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.SetProvider(JavaInfoProvider, JavaInfo{ HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile), + TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars, + TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars, ImplementationAndResourcesJars: android.PathsIfNonNil(j.combinedClasspathFile), ImplementationJars: android.PathsIfNonNil(j.combinedClasspathFile), AidlIncludeDirs: j.exportAidlIncludeDirs, @@ -2396,6 +2431,7 @@ func DefaultsFactory() android.Module { &RuntimeResourceOverlayProperties{}, &LintProperties{}, &appTestHelperAppProperties{}, + &JavaApiLibraryProperties{}, ) android.InitDefaultsModule(module) @@ -2520,9 +2556,10 @@ func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorConte type javaCommonAttributes struct { *javaResourcesAttributes - Srcs bazel.LabelListAttribute - Plugins bazel.LabelListAttribute - Javacopts bazel.StringListAttribute + Srcs bazel.LabelListAttribute + Plugins bazel.LabelListAttribute + Javacopts bazel.StringListAttribute + Common_srcs bazel.LabelListAttribute } type javaDependencyLabels struct { @@ -2560,7 +2597,7 @@ type bp2BuildJavaInfo struct { // to be returned to the calling function. func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo) { var srcs bazel.LabelListAttribute - var deps bazel.LabelList + var deps bazel.LabelListAttribute var staticDeps bazel.LabelList archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) @@ -2666,18 +2703,17 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) Javacopts: bazel.MakeStringListAttribute(javacopts), } - if m.properties.Libs != nil { - - // TODO 244210934 ALIX Check if this else statement breaks presubmits get rid of it if it doesn't - if strings.HasPrefix(ctx.ModuleType(), "java_binary") || strings.HasPrefix(ctx.ModuleType(), "java_library") || ctx.ModuleType() == "android_library" { - for _, d := range m.properties.Libs { - neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d) - neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink" - deps.Add(&neverlinkLabel) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*CommonProperties); ok { + var libLabels []bazel.Label + for _, d := range archProps.Libs { + neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d) + neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink" + libLabels = append(libLabels, neverlinkLabel) + } + deps.SetSelectValue(axis, config, bazel.MakeLabelList(libLabels)) } - - } else { - deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) } } @@ -2695,7 +2731,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) staticDeps.Add(protoDepLabel) depLabels := &javaDependencyLabels{} - depLabels.Deps = bazel.MakeLabelListAttribute(deps) + depLabels.Deps = deps depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) bp2BuildInfo := &bp2BuildJavaInfo{ @@ -2708,10 +2744,9 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) type javaLibraryAttributes struct { *javaCommonAttributes - Deps bazel.LabelListAttribute - Exports bazel.LabelListAttribute - Neverlink bazel.BoolAttribute - Common_srcs bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Exports bazel.LabelListAttribute + Neverlink bazel.BoolAttribute } func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { @@ -2745,7 +2780,7 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { Bzl_load_location: "//build/bazel/rules/java:library.bzl", } } else { - attrs.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)) + attrs.javaCommonAttributes.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)) props = bazel.BazelTargetModuleProperties{ Rule_class: "kt_jvm_library", @@ -2801,14 +2836,8 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { mainClass = mainClassInManifest } - attrs := &javaBinaryHostAttributes{ - javaCommonAttributes: commonAttrs, - Deps: deps, - Runtime_deps: runtimeDeps, - Main_class: mainClass, - } - // Attribute jvm_flags + var jvmFlags bazel.StringListAttribute if m.binaryProperties.Jni_libs != nil { jniLibPackages := map[string]bool{} for _, jniLibLabel := range android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs).Includes { @@ -2831,12 +2860,56 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage) } - attrs.Jvm_flags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")}) + jvmFlags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")}) } props := bazel.BazelTargetModuleProperties{ Rule_class: "java_binary", } + attrs := &javaBinaryHostAttributes{ + Runtime_deps: runtimeDeps, + Main_class: mainClass, + Jvm_flags: jvmFlags, + } + + if !bp2BuildInfo.hasKotlinSrcs && len(m.properties.Common_srcs) == 0 { + attrs.javaCommonAttributes = commonAttrs + attrs.Deps = deps + } else { + ktName := m.Name() + "_kt" + ktProps := bazel.BazelTargetModuleProperties{ + Rule_class: "kt_jvm_library", + Bzl_load_location: "@rules_kotlin//kotlin:jvm_library.bzl", + } + ktAttrs := &javaLibraryAttributes{ + Deps: deps, + javaCommonAttributes: &javaCommonAttributes{ + Srcs: commonAttrs.Srcs, + Plugins: commonAttrs.Plugins, + Javacopts: commonAttrs.Javacopts, + }, + } + + if len(m.properties.Common_srcs) != 0 { + ktAttrs.javaCommonAttributes.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs)) + } + + // kt_jvm_library does not support resource_strip_prefix, if this attribute + // is set, than javaResourcesAttributes needs to be set in the + // javaCommonAttributes of the java_binary target + if commonAttrs.javaResourcesAttributes != nil { + if commonAttrs.javaResourcesAttributes.Resource_strip_prefix != nil { + attrs.javaCommonAttributes = &javaCommonAttributes{ + javaResourcesAttributes: commonAttrs.javaResourcesAttributes, + } + } else { + ktAttrs.javaCommonAttributes.javaResourcesAttributes = commonAttrs.javaResourcesAttributes + } + } + + ctx.CreateBazelTargetModule(ktProps, android.CommonAttributes{Name: ktName}, ktAttrs) + attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + ktName}}) + } // Create the BazelTargetModule. ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) diff --git a/java/java_test.go b/java/java_test.go index 085f6272a..21993eccf 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -30,7 +30,6 @@ import ( "android/soong/cc" "android/soong/dexpreopt" "android/soong/genrule" - "android/soong/python" ) // Legacy preparer used for running tests within the java package. @@ -49,7 +48,6 @@ var prepareForJavaTest = android.GroupFixturePreparers( // Include all the default java modules. PrepareForTestWithJavaDefaultModules, PrepareForTestWithOverlayBuildComponents, - python.PrepareForTestWithPythonBuildComponents, android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) { ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory) }), @@ -1440,24 +1438,26 @@ func TestAidlEnforcePermissionsException(t *testing.T) { } func TestDataNativeBinaries(t *testing.T) { - ctx, _ := testJava(t, ` + ctx := android.GroupFixturePreparers( + prepareForJavaTest, + android.PrepareForTestWithAllowMissingDependencies).RunTestWithBp(t, ` java_test_host { name: "foo", srcs: ["a.java"], data_native_bins: ["bin"] } - python_binary_host { + cc_binary_host { name: "bin", - srcs: ["bin.py"], + srcs: ["bin.cpp"], } - `) + `).TestContext buildOS := ctx.Config().BuildOS.String() test := ctx.ModuleForTests("foo", buildOS+"_common").Module().(*TestHost) entries := android.AndroidMkEntriesForTest(t, ctx, test)[0] - expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64_PY3/bin:bin"} + expected := []string{"out/soong/.intermediates/bin/" + buildOS + "_x86_64/bin:bin"} actual := entries.EntryMap["LOCAL_COMPATIBILITY_SUPPORT_FILES"] android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_COMPATIBILITY_SUPPORT_FILES", ctx.Config(), expected, actual) } @@ -1840,6 +1840,20 @@ func TestDeviceBinaryWrapperGeneration(t *testing.T) { }`) } +func TestJavaApiContributionEmptyApiFile(t *testing.T) { + testJavaError(t, + "Error: foo has an empty api file.", + `java_api_contribution { + name: "foo", + } + java_api_library { + name: "bar", + api_surface: "public", + api_contributions: ["foo"], + } + `) +} + func TestJavaApiLibraryAndProviderLink(t *testing.T) { provider_bp_a := ` java_api_contribution { @@ -1894,6 +1908,98 @@ func TestJavaApiLibraryAndProviderLink(t *testing.T) { } } +func TestJavaApiLibraryAndDefaultsLink(t *testing.T) { + provider_bp_a := ` + java_api_contribution { + name: "foo1", + api_file: "foo1.txt", + } + ` + provider_bp_b := ` + java_api_contribution { + name: "foo2", + api_file: "foo2.txt", + } + ` + provider_bp_c := ` + java_api_contribution { + name: "foo3", + api_file: "foo3.txt", + } + ` + provider_bp_d := ` + java_api_contribution { + name: "foo4", + api_file: "foo4.txt", + } + ` + ctx, _ := testJavaWithFS(t, ` + java_defaults { + name: "baz1", + api_surface: "public", + api_contributions: ["foo1", "foo2"], + } + + java_defaults { + name: "baz2", + api_surface: "system", + api_contributions: ["foo3"], + } + + java_api_library { + name: "bar1", + api_surface: "public", + api_contributions: ["foo1"], + } + + java_api_library { + name: "bar2", + api_surface: "public", + defaults:["baz1"], + } + + java_api_library { + name: "bar3", + api_surface: "system", + defaults:["baz1", "baz2"], + api_contributions: ["foo4"], + api_files: ["api1/current.txt", "api2/current.txt"] + } + `, + map[string][]byte{ + "a/Android.bp": []byte(provider_bp_a), + "b/Android.bp": []byte(provider_bp_b), + "c/Android.bp": []byte(provider_bp_c), + "d/Android.bp": []byte(provider_bp_d), + }) + + testcases := []struct { + moduleName string + sourceTextFileDirs []string + }{ + { + moduleName: "bar1", + sourceTextFileDirs: []string{"a/foo1.txt"}, + }, + { + moduleName: "bar2", + sourceTextFileDirs: []string{"a/foo1.txt", "b/foo2.txt"}, + }, + { + moduleName: "bar3", + sourceTextFileDirs: []string{"c/foo3.txt", "a/foo1.txt", "b/foo2.txt", "d/foo4.txt", "api1/current.txt", "api2/current.txt"}, + }, + } + for _, c := range testcases { + m := ctx.ModuleForTests(c.moduleName, "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ") + android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag) + } +} + func TestJavaApiLibraryJarGeneration(t *testing.T) { provider_bp_a := ` java_api_contribution { @@ -1901,7 +2007,8 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { api_file: "foo1.txt", } ` - provider_bp_b := `java_api_contribution { + provider_bp_b := ` + java_api_contribution { name: "foo2", api_file: "foo2.txt", } @@ -1946,6 +2053,81 @@ func TestJavaApiLibraryJarGeneration(t *testing.T) { } } +func TestJavaApiLibraryLibsLink(t *testing.T) { + provider_bp_a := ` + java_api_contribution { + name: "foo1", + api_file: "foo1.txt", + } + ` + provider_bp_b := ` + java_api_contribution { + name: "foo2", + api_file: "foo2.txt", + } + ` + lib_bp_a := ` + java_library { + name: "lib1", + srcs: ["Lib.java"], + } + ` + lib_bp_b := ` + java_library { + name: "lib2", + srcs: ["Lib.java"], + } + ` + + ctx, _ := testJavaWithFS(t, ` + java_api_library { + name: "bar1", + api_surface: "public", + api_contributions: ["foo1"], + libs: ["lib1"], + } + + java_api_library { + name: "bar2", + api_surface: "system", + api_contributions: ["foo1", "foo2"], + libs: ["lib1", "lib2", "bar1"], + } + `, + map[string][]byte{ + "a/Android.bp": []byte(provider_bp_a), + "b/Android.bp": []byte(provider_bp_b), + "c/Android.bp": []byte(lib_bp_a), + "c/Lib.java": {}, + "d/Android.bp": []byte(lib_bp_b), + "d/Lib.java": {}, + }) + + testcases := []struct { + moduleName string + classPathJarNames []string + }{ + { + moduleName: "bar1", + classPathJarNames: []string{"lib1.jar"}, + }, + { + moduleName: "bar2", + classPathJarNames: []string{"lib1.jar", "lib2.jar", "bar1/android.jar"}, + }, + } + for _, c := range testcases { + m := ctx.ModuleForTests(c.moduleName, "android_common") + javacRules := m.Rule("javac") + classPathArgs := javacRules.Args["classpath"] + for _, jarName := range c.classPathJarNames { + if !strings.Contains(classPathArgs, jarName) { + t.Errorf("Module output does not contain expected jar %s", jarName) + } + } + } +} + func TestTradefedOptions(t *testing.T) { result := PrepareForTestWithJavaBuildComponents.RunTestWithBp(t, ` java_test_host { diff --git a/java/kotlin_test.go b/java/kotlin_test.go index 491ce2939..933fc5187 100644 --- a/java/kotlin_test.go +++ b/java/kotlin_test.go @@ -44,6 +44,10 @@ func TestKotlin(t *testing.T) { kotlinStdlib := ctx.ModuleForTests("kotlin-stdlib", "android_common"). Output("turbine-combined/kotlin-stdlib.jar").Output + kotlinStdlibJdk7 := ctx.ModuleForTests("kotlin-stdlib-jdk7", "android_common"). + Output("turbine-combined/kotlin-stdlib-jdk7.jar").Output + kotlinStdlibJdk8 := ctx.ModuleForTests("kotlin-stdlib-jdk8", "android_common"). + Output("turbine-combined/kotlin-stdlib-jdk8.jar").Output kotlinAnnotations := ctx.ModuleForTests("kotlin-annotations", "android_common"). Output("turbine-combined/kotlin-annotations.jar").Output @@ -79,6 +83,16 @@ func TestKotlin(t *testing.T) { fooJar.Inputs.Strings(), kotlinStdlib.String()) } + if !inList(kotlinStdlibJdk7.String(), fooJar.Inputs.Strings()) { + t.Errorf("foo jar inputs %v does not contain %v", + fooJar.Inputs.Strings(), kotlinStdlibJdk7.String()) + } + + if !inList(kotlinStdlibJdk8.String(), fooJar.Inputs.Strings()) { + t.Errorf("foo jar inputs %v does not contain %v", + fooJar.Inputs.Strings(), kotlinStdlibJdk8.String()) + } + if !inList(kotlinAnnotations.String(), fooJar.Inputs.Strings()) { t.Errorf("foo jar inputs %v does not contain %v", fooJar.Inputs.Strings(), kotlinAnnotations.String()) diff --git a/java/sdk_library.go b/java/sdk_library.go index 3b64bf733..b87236596 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1599,6 +1599,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC Srcs []string Installable *bool Sdk_version *string + Api_surface *string System_modules *string Libs []string Output_javadoc_comments *bool @@ -1638,6 +1639,7 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC props.Srcs = append(props.Srcs, module.properties.Srcs...) props.Srcs = append(props.Srcs, module.sdkLibraryProperties.Api_srcs...) props.Sdk_version = module.deviceProperties.Sdk_version + props.Api_surface = &apiScope.name props.System_modules = module.deviceProperties.System_modules props.Installable = proptools.BoolPtr(false) // A droiddoc module has only one Libs property and doesn't distinguish between |