diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 598 |
1 files changed, 490 insertions, 108 deletions
diff --git a/java/java.go b/java/java.go index b163bf8f8..b6fc6b831 100644 --- a/java/java.go +++ b/java/java.go @@ -24,6 +24,7 @@ import ( "strings" "android/soong/bazel" + "android/soong/bazel/cquery" "github.com/google/blueprint" "github.com/google/blueprint/proptools" @@ -65,6 +66,8 @@ func registerJavaBuildComponents(ctx android.RegistrationContext) { // to support the checks in dexpreoptDisabled(). ctx.FinalDepsMutators(func(ctx android.RegisterMutatorsContext) { ctx.BottomUp("dexpreopt_tool_deps", dexpreoptToolDepsMutator).Parallel() + // needs access to ApexInfoProvider which is available after variant creation + ctx.BottomUp("jacoco_deps", jacocoDepsMutator).Parallel() }) ctx.RegisterSingletonType("logtags", LogtagsSingleton) @@ -118,6 +121,16 @@ var ( copyEverythingToSnapshot, } + snapshotRequiresImplementationJar = func(ctx android.SdkMemberContext) bool { + // In the S build the build will break if updatable-media does not provide a full implementation + // jar. That issue was fixed in Tiramisu by b/229932396. + if ctx.IsTargetBuildBeforeTiramisu() && ctx.Name() == "updatable-media" { + return true + } + + return false + } + // Supports adding java boot libraries to module_exports and sdk. // // The build has some implicit dependencies (via the boot jars configuration) on a number of @@ -135,13 +148,21 @@ var ( SupportsSdk: true, }, func(ctx android.SdkMemberContext, j *Library) android.Path { + if snapshotRequiresImplementationJar(ctx) { + return exportImplementationClassesJar(ctx, j) + } + // Java boot libs are only provided in the SDK to provide access to their dex implementation // jar for use by dexpreopting and boot jars package check. They do not need to provide an // actual implementation jar but the java_import will need a file that exists so just copy an // empty file. Any attempt to use that file as a jar will cause a build error. return ctx.SnapshotBuilder().EmptyFile() }, - func(osPrefix, name string) string { + func(ctx android.SdkMemberContext, osPrefix, name string) string { + if snapshotRequiresImplementationJar(ctx) { + return sdkSnapshotFilePathForJar(ctx, osPrefix, name) + } + // Create a special name for the implementation jar to try and provide some useful information // to a developer that attempts to compile against this. // TODO(b/175714559): Provide a proper error message in Soong not ninja. @@ -164,6 +185,9 @@ var ( android.SdkMemberTypeBase{ PropertyName: "java_systemserver_libs", SupportsSdk: true, + + // This was only added in Tiramisu. + SupportedBuildReleaseSpecification: "Tiramisu+", }, func(ctx android.SdkMemberContext, j *Library) android.Path { // Java systemserver libs are only provided in the SDK to provide access to their dex @@ -172,7 +196,7 @@ var ( // file. Any attempt to use that file as a jar will cause a build error. return ctx.SnapshotBuilder().EmptyFile() }, - func(osPrefix, name string) string { + func(_ android.SdkMemberContext, osPrefix, name string) string { // Create a special name for the implementation jar to try and provide some useful information // to a developer that attempts to compile against this. // TODO(b/175714559): Provide a proper error message in Soong not ninja. @@ -187,6 +211,14 @@ var ( PropertyName: "java_tests", }, } + + // Rule for generating device binary default wrapper + deviceBinaryWrapper = pctx.StaticRule("deviceBinaryWrapper", blueprint.RuleParams{ + Command: `echo -e '#!/system/bin/sh\n` + + `export CLASSPATH=/system/framework/$jar_name\n` + + `exec app_process /$partition/bin $main_class "$$@"'> ${out}`, + Description: "Generating device binary wrapper ${jar_name}", + }, "jar_name", "partition", "main_class") ) // JavaInfo contains information about a java module for use by modules that depend on it. @@ -300,19 +332,11 @@ var _ android.LicenseAnnotationsDependencyTag = dependencyTag{} type usesLibraryDependencyTag struct { dependencyTag - - // SDK version in which the library appared as a standalone library. - sdkVersion int - - // If the dependency is optional or required. - optional bool - - // Whether this is an implicit dependency inferred by Soong, or an explicit one added via - // `uses_libs`/`optional_uses_libs` properties. - implicit bool + sdkVersion int // SDK version in which the library appared as a standalone library. + optional bool // If the dependency is optional or required. } -func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag { +func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag { return usesLibraryDependencyTag{ dependencyTag: dependencyTag{ name: fmt.Sprintf("uses-library-%d", sdkVersion), @@ -320,7 +344,6 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) }, sdkVersion: sdkVersion, optional: optional, - implicit: implicit, } } @@ -333,6 +356,7 @@ var ( dataDeviceBinsTag = dependencyTag{name: "dataDeviceBins"} staticLibTag = dependencyTag{name: "staticlib"} libTag = dependencyTag{name: "javalib", runtimeLinked: true} + sdkLibTag = dependencyTag{name: "sdklib", runtimeLinked: true} java9LibTag = dependencyTag{name: "java9lib", runtimeLinked: true} pluginTag = dependencyTag{name: "plugin", toolchain: true} errorpronePluginTag = dependencyTag{name: "errorprone-plugin", toolchain: true} @@ -351,10 +375,15 @@ var ( syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"} jniInstallTag = installDependencyTag{name: "jni install"} binaryInstallTag = installDependencyTag{name: "binary install"} + usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false) + usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true) + usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true) + usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false) + usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true) ) func IsLibDepTag(depTag blueprint.DependencyTag) bool { - return depTag == libTag + return depTag == libTag || depTag == sdkLibTag } func IsStaticLibDepTag(depTag blueprint.DependencyTag) bool { @@ -400,6 +429,7 @@ type jniLib struct { target android.Target coverageFile android.OptionalPath unstrippedFile android.Path + partition string } func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) { @@ -407,7 +437,7 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, if sdkDep.useModule { ctx.AddVariationDependencies(nil, bootClasspathTag, sdkDep.bootclasspath...) ctx.AddVariationDependencies(nil, java9LibTag, sdkDep.java9Classpath...) - ctx.AddVariationDependencies(nil, libTag, sdkDep.classpath...) + ctx.AddVariationDependencies(nil, sdkLibTag, sdkDep.classpath...) if d.effectiveOptimizeEnabled() && sdkDep.hasStandardLibs() { ctx.AddVariationDependencies(nil, proguardRaiseTag, config.LegacyCorePlatformBootclasspathLibraries...) } @@ -472,6 +502,12 @@ func getJavaVersion(ctx android.ModuleContext, javaVersion string, sdkContext an return normalizeJavaVersion(ctx, javaVersion) } else if ctx.Device() { return defaultJavaLanguageVersion(ctx, sdkContext.SdkVersion(ctx)) + } else if ctx.Config().TargetsJava17() { + // Temporary experimental flag to be able to try and build with + // java version 17 options. The flag, if used, just sets Java + // 17 as the default version, leaving any components that + // target an older version intact. + return JAVA_VERSION_17 } else { return JAVA_VERSION_11 } @@ -486,6 +522,7 @@ const ( JAVA_VERSION_8 = 8 JAVA_VERSION_9 = 9 JAVA_VERSION_11 = 11 + JAVA_VERSION_17 = 17 ) func (v javaVersion) String() string { @@ -500,11 +537,27 @@ func (v javaVersion) String() string { return "1.9" case JAVA_VERSION_11: return "11" + case JAVA_VERSION_17: + return "17" default: return "unsupported" } } +func (v javaVersion) StringForKotlinc() string { + // $ ./external/kotlinc/bin/kotlinc -jvm-target foo + // error: unknown JVM target version: foo + // Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17 + switch v { + case JAVA_VERSION_7: + return "1.6" + case JAVA_VERSION_9: + return "9" + default: + return v.String() + } +} + // Returns true if javac targeting this version uses system modules instead of a bootclasspath. func (v javaVersion) usesJavaModules() bool { return v >= 9 @@ -522,8 +575,10 @@ func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) jav return JAVA_VERSION_9 case "11": return JAVA_VERSION_11 - case "10": - ctx.PropertyErrorf("java_version", "Java language levels 10 is not supported") + case "17": + return JAVA_VERSION_17 + case "10", "12", "13", "14", "15", "16": + ctx.PropertyErrorf("java_version", "Java language level %s is not supported", javaVersion) return JAVA_VERSION_UNSUPPORTED default: ctx.PropertyErrorf("java_version", "Unrecognized Java language level") @@ -586,6 +641,9 @@ func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer } func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { + + j.provideHiddenAPIPropertyInfo(ctx) + j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) j.maxSdkVersion = j.MaxSdkVersion(ctx) @@ -596,12 +654,14 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { } j.checkSdkVersions(ctx) - j.dexpreopter.installPath = j.dexpreopter.getInstallPath( - ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) - j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary - setUncompressDex(ctx, &j.dexpreopter, &j.dexer) - j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex - j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + if ctx.Device() { + j.dexpreopter.installPath = j.dexpreopter.getInstallPath( + ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar")) + j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary + setUncompressDex(ctx, &j.dexpreopter, &j.dexer) + j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex + j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx) + } j.compile(ctx, nil) // Collect the module directory for IDE info in java/jdeps.go. @@ -646,7 +706,7 @@ const ( ) // path to the jar file of a java library. Relative to <sdk_root>/<api_dir> -func sdkSnapshotFilePathForJar(osPrefix, name string) string { +func sdkSnapshotFilePathForJar(_ android.SdkMemberContext, osPrefix, name string) string { return sdkSnapshotFilePathForMember(osPrefix, name, jarFileSuffix) } @@ -663,7 +723,7 @@ type librarySdkMemberType struct { // Function to compute the snapshot relative path to which the named library's // jar should be copied. - snapshotPathGetter func(osPrefix, name string) string + snapshotPathGetter func(ctx android.SdkMemberContext, osPrefix, name string) string // True if only the jar should be copied to the snapshot, false if the jar plus any additional // files like aidl files should also be copied. @@ -721,7 +781,7 @@ func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberConte exportedJar := p.JarToExport if exportedJar != nil { // Delegate the creation of the snapshot relative path to the member type. - snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(p.OsPrefix(), ctx.Name()) + snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(ctx, p.OsPrefix(), ctx.Name()) // Copy the exported jar to the snapshot. builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) @@ -807,11 +867,10 @@ func LibraryHostFactory() android.Module { // Test option struct. type TestOptions struct { + android.CommonTestOptions + // a list of extra test configuration files that should be installed with the module. Extra_test_configs []string `android:"path,arch_variant"` - - // If the test is a hostside(no device required) unittest that shall be run during presubmit check. - Unit_test *bool } type testProperties struct { @@ -855,7 +914,25 @@ type hostTestProperties struct { Data_native_bins []string `android:"arch_variant"` // list of device binary modules that should be installed alongside the test - Data_device_bins []string `android:"arch_variant"` + // This property only adds the first variant of the dependency + Data_device_bins_first []string `android:"arch_variant"` + + // list of device binary modules that should be installed alongside the test + // This property adds 64bit AND 32bit variants of the dependency + Data_device_bins_both []string `android:"arch_variant"` + + // list of device binary modules that should be installed alongside the test + // This property only adds 64bit variants of the dependency + Data_device_bins_64 []string `android:"arch_variant"` + + // list of device binary modules that should be installed alongside the test + // This property adds 32bit variants of the dependency if available, or else + // defaults to the 64bit variant + Data_device_bins_prefer32 []string `android:"arch_variant"` + + // list of device binary modules that should be installed alongside the test + // This property only adds 32bit variants of the dependency + Data_device_bins_32 []string `android:"arch_variant"` } type testHelperLibraryProperties struct { @@ -922,6 +999,83 @@ func (j *JavaTestImport) InstallInTestcases() bool { return true } +func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) { + if len(j.testHostProperties.Data_device_bins_first) > 0 { + deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations() + ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_first...) + } + + var maybeAndroid32Target *android.Target + var maybeAndroid64Target *android.Target + android32TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib32") + android64TargetList := android.FirstTarget(ctx.Config().Targets[android.Android], "lib64") + if len(android32TargetList) > 0 { + maybeAndroid32Target = &android32TargetList[0] + } + if len(android64TargetList) > 0 { + maybeAndroid64Target = &android64TargetList[0] + } + + if len(j.testHostProperties.Data_device_bins_both) > 0 { + if maybeAndroid32Target == nil && maybeAndroid64Target == nil { + ctx.PropertyErrorf("data_device_bins_both", "no device targets available. Targets: %q", ctx.Config().Targets) + return + } + if maybeAndroid32Target != nil { + ctx.AddFarVariationDependencies( + maybeAndroid32Target.Variations(), + dataDeviceBinsTag, + j.testHostProperties.Data_device_bins_both..., + ) + } + if maybeAndroid64Target != nil { + ctx.AddFarVariationDependencies( + maybeAndroid64Target.Variations(), + dataDeviceBinsTag, + j.testHostProperties.Data_device_bins_both..., + ) + } + } + + if len(j.testHostProperties.Data_device_bins_prefer32) > 0 { + if maybeAndroid32Target != nil { + ctx.AddFarVariationDependencies( + maybeAndroid32Target.Variations(), + dataDeviceBinsTag, + j.testHostProperties.Data_device_bins_prefer32..., + ) + } else { + if maybeAndroid64Target == nil { + ctx.PropertyErrorf("data_device_bins_prefer32", "no device targets available. Targets: %q", ctx.Config().Targets) + return + } + ctx.AddFarVariationDependencies( + maybeAndroid64Target.Variations(), + dataDeviceBinsTag, + j.testHostProperties.Data_device_bins_prefer32..., + ) + } + } + + if len(j.testHostProperties.Data_device_bins_32) > 0 { + if maybeAndroid32Target == nil { + ctx.PropertyErrorf("data_device_bins_32", "cannot find 32bit device target. Targets: %q", ctx.Config().Targets) + return + } + deviceVariations := maybeAndroid32Target.Variations() + ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_32...) + } + + if len(j.testHostProperties.Data_device_bins_64) > 0 { + if maybeAndroid64Target == nil { + ctx.PropertyErrorf("data_device_bins_64", "cannot find 64bit device target. Targets: %q", ctx.Config().Targets) + return + } + deviceVariations := maybeAndroid64Target.Variations() + ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins_64...) + } +} + func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) { if len(j.testHostProperties.Data_native_bins) > 0 { for _, target := range ctx.MultiTargets() { @@ -929,11 +1083,6 @@ func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) { } } - if len(j.testHostProperties.Data_device_bins) > 0 { - deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations() - ctx.AddFarVariationDependencies(deviceVariations, dataDeviceBinsTag, j.testHostProperties.Data_device_bins...) - } - if len(j.testProperties.Jni_libs) > 0 { for _, target := range ctx.MultiTargets() { sharedLibVariations := append(target.Variations(), blueprint.Variation{Mutator: "link", Variation: "shared"}) @@ -941,6 +1090,8 @@ func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) { } } + j.addDataDeviceBinsDeps(ctx) + j.deps(ctx) } @@ -948,17 +1099,40 @@ func (j *TestHost) AddExtraResource(p android.Path) { j.extraResources = append(j.extraResources, p) } +func (j *TestHost) dataDeviceBins() []string { + ret := make([]string, 0, + len(j.testHostProperties.Data_device_bins_first)+ + len(j.testHostProperties.Data_device_bins_both)+ + len(j.testHostProperties.Data_device_bins_prefer32)+ + len(j.testHostProperties.Data_device_bins_32)+ + len(j.testHostProperties.Data_device_bins_64), + ) + + ret = append(ret, j.testHostProperties.Data_device_bins_first...) + ret = append(ret, j.testHostProperties.Data_device_bins_both...) + ret = append(ret, j.testHostProperties.Data_device_bins_prefer32...) + ret = append(ret, j.testHostProperties.Data_device_bins_32...) + ret = append(ret, j.testHostProperties.Data_device_bins_64...) + + return ret +} + func (j *TestHost) GenerateAndroidBuildActions(ctx android.ModuleContext) { var configs []tradefed.Config - if len(j.testHostProperties.Data_device_bins) > 0 { + dataDeviceBins := j.dataDeviceBins() + if len(dataDeviceBins) > 0 { // add Tradefed configuration to push device bins to device for testing remoteDir := filepath.Join("/data/local/tests/unrestricted/", j.Name()) options := []tradefed.Option{{Name: "cleanup", Value: "true"}} - for _, bin := range j.testHostProperties.Data_device_bins { + for _, bin := range dataDeviceBins { fullPath := filepath.Join(remoteDir, bin) options = append(options, tradefed.Option{Name: "push-file", Key: bin, Value: fullPath}) } - configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.PushFilePreparer", options}) + configs = append(configs, tradefed.Object{ + Type: "target_preparer", + Class: "com.android.tradefed.targetprep.PushFilePreparer", + Options: options, + }) } j.Test.generateAndroidBuildActionsWithConfig(ctx, configs) @@ -1072,7 +1246,7 @@ func (p *testSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, exportedJar := p.JarToExport if exportedJar != nil { - snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name()) + snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(ctx, p.OsPrefix(), ctx.Name()) builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath) propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath}) @@ -1102,7 +1276,7 @@ func TestFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true - module.Module.linter.test = true + module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) android.InitSdkAwareModule(module) InitJavaModule(module, android.HostAndDeviceSupported) @@ -1118,7 +1292,7 @@ func TestHelperLibraryFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) module.Module.dexpreopter.isTest = true - module.Module.linter.test = true + module.Module.linter.properties.Lint.Test = proptools.BoolPtr(true) InitJavaModule(module, android.HostAndDeviceSupported) return module @@ -1232,7 +1406,31 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("wrapper", "wrapper is required for Windows") } - j.wrapperFile = android.PathForSource(ctx, "build/soong/scripts/jar-wrapper.sh") + 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 := "" @@ -1249,10 +1447,10 @@ func (j *Binary) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func (j *Binary) DepsMutator(ctx android.BottomUpMutatorContext) { - if ctx.Arch().ArchType == android.Common || ctx.BazelConversionMode() { + if ctx.Arch().ArchType == android.Common { j.deps(ctx) } - if ctx.Arch().ArchType != android.Common || ctx.BazelConversionMode() { + if ctx.Arch().ArchType != android.Common { // These dependencies ensure the host installation rules will install the jar file and // the jni libraries when the wrapper is installed. ctx.AddVariationDependencies(nil, jniInstallTag, j.binaryProperties.Jni_libs...) @@ -1318,6 +1516,10 @@ type ImportProperties struct { // specified. Min_sdk_version *string + // The max sdk version placeholder used to replace maxSdkVersion attributes on permission + // and uses-permission tags in manifest_fixer. + Replace_max_sdk_version_placeholder *string + Installable *bool // If not empty, classes are restricted to the specified packages and their sub-packages. @@ -1397,6 +1599,13 @@ func (j *Import) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } +func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec { + if j.properties.Replace_max_sdk_version_placeholder != nil { + return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder) + } + return android.SdkSpecFrom(ctx, "") +} + func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec { return j.SdkVersion(ctx) } @@ -1440,7 +1649,8 @@ func (j *Import) DepsMutator(ctx android.BottomUpMutatorContext) { } } -func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { +func (j *Import) commonBuildActions(ctx android.ModuleContext) { + //TODO(b/231322772) these should come from Bazel once available j.sdkVersion = j.SdkVersion(ctx) j.minSdkVersion = j.MinSdkVersion(ctx) @@ -1451,6 +1661,10 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if ctx.Windows() { j.HideFromMake() } +} + +func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { + j.commonBuildActions(ctx) jars := android.PathsForModuleSrc(ctx, j.properties.Jars) @@ -1474,7 +1688,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if ctx.OtherModuleHasProvider(module, JavaInfoProvider) { dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) switch tag { - case libTag: + case libTag, sdkLibTag: flags.classpath = append(flags.classpath, dep.HeaderJars...) flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...) case staticLibTag: @@ -1484,7 +1698,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } else if dep, ok := module.(SdkLibraryDependency); ok { switch tag { - case libTag: + case libTag, sdkLibTag: flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...) } } @@ -1492,19 +1706,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { addCLCFromDep(ctx, module, j.classLoaderContexts) }) - if Bool(j.properties.Installable) { - var installDir android.InstallPath - if ctx.InstallInTestcases() { - var archDir string - if !ctx.Host() { - archDir = ctx.DeviceConfig().DeviceArch() - } - installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir) - } else { - installDir = android.PathForModuleInstall(ctx, "framework") - } - ctx.InstallFile(installDir, jarName, outputFile) - } + j.maybeInstall(ctx, jarName, outputFile) j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs) @@ -1578,6 +1780,24 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) } +func (j *Import) maybeInstall(ctx android.ModuleContext, jarName string, outputFile android.Path) { + if !Bool(j.properties.Installable) { + return + } + + var installDir android.InstallPath + if ctx.InstallInTestcases() { + var archDir string + if !ctx.Host() { + archDir = ctx.DeviceConfig().DeviceArch() + } + installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir) + } else { + installDir = android.PathForModuleInstall(ctx, "framework") + } + ctx.InstallFile(installDir, jarName, outputFile) +} + func (j *Import) OutputFiles(tag string) (android.Paths, error) { switch tag { case "", ".jar": @@ -1876,9 +2096,7 @@ func DexImportFactory() android.Module { return module } -// // Defaults -// type Defaults struct { android.ModuleBase android.DefaultsModuleBase @@ -1893,29 +2111,29 @@ type Defaults struct { // // Example: // -// java_defaults { -// name: "example_defaults", -// srcs: ["common/**/*.java"], -// javacflags: ["-Xlint:all"], -// aaptflags: ["--auto-add-overlay"], -// } +// java_defaults { +// name: "example_defaults", +// srcs: ["common/**/*.java"], +// javacflags: ["-Xlint:all"], +// aaptflags: ["--auto-add-overlay"], +// } // -// java_library { -// name: "example", -// defaults: ["example_defaults"], -// srcs: ["example/**/*.java"], -// } +// java_library { +// name: "example", +// defaults: ["example_defaults"], +// srcs: ["example/**/*.java"], +// } // // is functionally identical to: // -// java_library { -// name: "example", -// srcs: [ -// "common/**/*.java", -// "example/**/*.java", -// ], -// javacflags: ["-Xlint:all"], -// } +// java_library { +// name: "example", +// srcs: [ +// "common/**/*.java", +// "example/**/*.java", +// ], +// javacflags: ["-Xlint:all"], +// } func DefaultsFactory() android.Module { module := &Defaults{} @@ -1994,12 +2212,10 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, } depTag := ctx.OtherModuleDependencyTag(depModule) - if depTag == libTag { + if IsLibDepTag(depTag) { // Ok, propagate <uses-library> through non-static library dependencies. - } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && - tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit { - // Ok, propagate <uses-library> through non-compatibility implicit <uses-library> - // dependencies. + } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion { + // Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies. } else if depTag == staticLibTag { // Propagate <uses-library> through static library dependencies, unless it is a component // library (such as stubs). Component libraries have a dependency on their SDK library, @@ -2017,14 +2233,56 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, // <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies // from its CLC should be added to the current CLC. if sdkLib != nil { - clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true, + clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts()) } else { clcMap.AddContextMap(dep.ClassLoaderContexts(), depName) } } +type javaResourcesAttributes struct { + Resources bazel.LabelListAttribute + Resource_strip_prefix *string +} + +func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes { + var resources bazel.LabelList + var resourceStripPrefix *string + + if m.properties.Java_resources != nil { + resources.Append(android.BazelLabelForModuleSrc(ctx, m.properties.Java_resources)) + } + + //TODO(b/179889880) handle case where glob includes files outside package + resDeps := ResourceDirsToFiles( + ctx, + m.properties.Java_resource_dirs, + m.properties.Exclude_java_resource_dirs, + m.properties.Exclude_java_resources, + ) + + for i, resDep := range resDeps { + dir, files := resDep.dir, resDep.files + + resources.Append(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files))) + + // Bazel includes the relative path from the WORKSPACE root when placing the resource + // inside the JAR file, so we need to remove that prefix + resourceStripPrefix = proptools.StringPtr(dir.String()) + if i > 0 { + // TODO(b/226423379) allow multiple resource prefixes + ctx.ModuleErrorf("bp2build does not support more than one directory in java_resource_dirs (b/226423379)") + } + } + + return &javaResourcesAttributes{ + Resources: bazel.MakeLabelListAttribute(resources), + Resource_strip_prefix: resourceStripPrefix, + } +} + type javaCommonAttributes struct { + *javaResourcesAttributes Srcs bazel.LabelListAttribute Plugins bazel.LabelListAttribute Javacopts bazel.StringListAttribute @@ -2037,16 +2295,27 @@ type javaDependencyLabels struct { StaticDeps bazel.LabelListAttribute } -// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules -// and also separates dependencies into dynamic dependencies and static dependencies. -// Each corresponding Bazel target type, can have a different method for handling -// dynamic vs. static dependencies, and so these are returned to the calling function. type eventLogTagsAttributes struct { Srcs bazel.LabelListAttribute } +type aidlLibraryAttributes struct { + Srcs bazel.LabelListAttribute +} + +type javaAidlLibraryAttributes struct { + Deps bazel.LabelListAttribute +} + +// convertLibraryAttrsBp2Build converts a few shared attributes from java_* modules +// and also separates dependencies into dynamic dependencies and static dependencies. +// Each corresponding Bazel target type, can have a different method for handling +// dynamic vs. static dependencies, and so these are returned to the calling function. func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *javaDependencyLabels) { var srcs bazel.LabelListAttribute + var deps bazel.LabelList + var staticDeps bazel.LabelList + archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{}) for axis, configToProps := range archVariantProps { for config, _props := range configToProps { @@ -2060,18 +2329,18 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) javaSrcPartition := "java" protoSrcPartition := "proto" logtagSrcPartition := "logtag" + aidlSrcPartition := "aidl" srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{ javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true}, logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}}, protoSrcPartition: android.ProtoSrcLabelPartition, + aidlSrcPartition: android.AidlSrcLabelPartition, }) javaSrcs := srcPartitions[javaSrcPartition] - var logtagsSrcs bazel.LabelList if !srcPartitions[logtagSrcPartition].IsEmpty() { logtagsLibName := m.Name() + "_logtags" - logtagsSrcs = bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}}) ctx.CreateBazelTargetModule( bazel.BazelTargetModuleProperties{ Rule_class: "event_log_tags", @@ -2082,13 +2351,55 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) Srcs: srcPartitions[logtagSrcPartition], }, ) + + logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}}) + javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs)) + } + + if !srcPartitions[aidlSrcPartition].IsEmpty() { + aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool { + return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName) + }) + + if !aidlSrcs.IsEmpty() { + aidlLibName := m.Name() + "_aidl_library" + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "aidl_library", + Bzl_load_location: "//build/bazel/rules/aidl:library.bzl", + }, + android.CommonAttributes{Name: aidlLibName}, + &aidlLibraryAttributes{ + Srcs: aidlSrcs, + }, + ) + aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}}) + } + + javaAidlLibName := m.Name() + "_java_aidl_library" + ctx.CreateBazelTargetModule( + bazel.BazelTargetModuleProperties{ + Rule_class: "java_aidl_library", + Bzl_load_location: "//build/bazel/rules/java:aidl_library.bzl", + }, + android.CommonAttributes{Name: javaAidlLibName}, + &javaAidlLibraryAttributes{ + Deps: aidlLibs, + }, + ) + + staticDeps.Add(&bazel.Label{Label: ":" + javaAidlLibName}) } - javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs)) var javacopts []string if m.properties.Javacflags != nil { javacopts = append(javacopts, m.properties.Javacflags...) } + if m.properties.Java_version != nil { + javaVersion := normalizeJavaVersion(ctx, *m.properties.Java_version).String() + javacopts = append(javacopts, fmt.Sprintf("-source %s -target %s", javaVersion, javaVersion)) + } + epEnabled := m.properties.Errorprone.Enabled //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable if Bool(epEnabled) { @@ -2096,23 +2407,31 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) } commonAttrs := &javaCommonAttributes{ - Srcs: javaSrcs, + Srcs: javaSrcs, + javaResourcesAttributes: m.convertJavaResourcesAttributes(ctx), Plugins: bazel.MakeLabelListAttribute( android.BazelLabelForModuleDeps(ctx, m.properties.Plugins), ), Javacopts: bazel.MakeStringListAttribute(javacopts), } - depLabels := &javaDependencyLabels{} - - var deps bazel.LabelList if m.properties.Libs != nil { - deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs)) + + // 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") { + for _, d := range m.properties.Libs { + neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d) + neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink" + deps.Add(&neverlinkLabel) + } + + } else { + deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs)))) + } } - var staticDeps bazel.LabelList if m.properties.Static_libs != nil { - staticDeps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs)) + staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs)))) } protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition]) @@ -2124,6 +2443,7 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) // and so this should be a static dependency. staticDeps.Add(protoDepLabel) + depLabels := &javaDependencyLabels{} depLabels.Deps = bazel.MakeLabelListAttribute(deps) depLabels.StaticDeps = bazel.MakeLabelListAttribute(staticDeps) @@ -2132,8 +2452,9 @@ func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) type javaLibraryAttributes struct { *javaCommonAttributes - Deps bazel.LabelListAttribute - Exports bazel.LabelListAttribute + Deps bazel.LabelListAttribute + Exports bazel.LabelListAttribute + Neverlink bazel.BoolAttribute } func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { @@ -2148,7 +2469,7 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { // TODO(b/220869005) remove forced dependency on current public android.jar deps.Add(bazel.MakeLabelAttribute("//prebuilts/sdk:public_current_android_sdk_java_import")) } - } else if !depLabels.Deps.IsEmpty() { + } else if !deps.IsEmpty() { ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.") } @@ -2163,7 +2484,8 @@ func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) { Bzl_load_location: "//build/bazel/rules/java:library.bzl", } - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs) + name := m.Name() + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) } type javaBinaryHostAttributes struct { @@ -2245,7 +2567,8 @@ func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) { } type bazelJavaImportAttributes struct { - Jars bazel.LabelListAttribute + Jars bazel.LabelListAttribute + Exports bazel.LabelListAttribute } // java_import bp2Build converter. @@ -2266,6 +2589,65 @@ func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } props := bazel.BazelTargetModuleProperties{Rule_class: "java_import"} - ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: android.RemoveOptionalPrebuiltPrefix(i.Name())}, attrs) + name := android.RemoveOptionalPrebuiltPrefix(i.Name()) + + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs) + neverlink := true + neverlinkAttrs := &javaLibraryAttributes{ + Neverlink: bazel.BoolAttribute{Value: &neverlink}, + Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}), + } + ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{Rule_class: "java_library"}, android.CommonAttributes{Name: name + "-neverlink"}, neverlinkAttrs) + +} + +var _ android.MixedBuildBuildable = (*Import)(nil) + +func (i *Import) getBazelModuleLabel(ctx android.BaseModuleContext) string { + return android.RemoveOptionalPrebuiltPrefixFromBazelLabel(i.GetBazelLabel(ctx, i)) +} + +func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) { + i.commonBuildActions(ctx) + + bazelCtx := ctx.Config().BazelContext + filePaths, err := bazelCtx.GetOutputFiles(i.getBazelModuleLabel(ctx), android.GetConfigKey(ctx)) + if err != nil { + ctx.ModuleErrorf(err.Error()) + return + } + + bazelJars := android.Paths{} + for _, bazelOutputFile := range filePaths { + bazelJars = append(bazelJars, android.PathForBazelOut(ctx, bazelOutputFile)) + } + + jarName := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ".jar" + outputFile := android.PathForModuleOut(ctx, "bazelCombined", jarName) + TransformJarsToJar(ctx, outputFile, "combine prebuilt jars", bazelJars, + android.OptionalPath{}, // manifest + false, // stripDirEntries + []string{}, // filesToStrip + []string{}, // dirsToStrip + ) + i.combinedClasspathFile = outputFile + + ctx.SetProvider(JavaInfoProvider, JavaInfo{ + HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile), + ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile), + ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile), + //TODO(b/240308299) include AIDL information from Bazel + }) + + i.maybeInstall(ctx, jarName, outputFile) +} + +func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) { + bazelCtx := ctx.Config().BazelContext + bazelCtx.QueueBazelRequest(i.getBazelModuleLabel(ctx), cquery.GetOutputFiles, android.GetConfigKey(ctx)) +} + +func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool { + return true } |
