summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/Android.bp66
-rw-r--r--java/androidmk.go21
-rwxr-xr-xjava/app.go31
-rw-r--r--java/app_builder.go44
-rw-r--r--java/app_test.go121
-rw-r--r--java/builder.go103
-rw-r--r--java/config/Android.bp15
-rw-r--r--java/config/config.go31
-rw-r--r--java/dex.go75
-rw-r--r--java/dexpreopt_bootjars.go4
-rw-r--r--java/java.go25
-rw-r--r--java/java_test.go27
-rw-r--r--java/sdk_library.go27
13 files changed, 506 insertions, 84 deletions
diff --git a/java/Android.bp b/java/Android.bp
new file mode 100644
index 000000000..2de1b8ea1
--- /dev/null
+++ b/java/Android.bp
@@ -0,0 +1,66 @@
+bootstrap_go_package {
+ name: "soong-java",
+ pkgPath: "android/soong/java",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ "soong-cc",
+ "soong-dexpreopt",
+ "soong-genrule",
+ "soong-java-config",
+ "soong-remoteexec",
+ "soong-tradefed",
+ ],
+ srcs: [
+ "aapt2.go",
+ "aar.go",
+ "android_manifest.go",
+ "android_resources.go",
+ "androidmk.go",
+ "app_builder.go",
+ "app.go",
+ "builder.go",
+ "device_host_converter.go",
+ "dex.go",
+ "dexpreopt.go",
+ "dexpreopt_bootjars.go",
+ "dexpreopt_config.go",
+ "droiddoc.go",
+ "gen.go",
+ "genrule.go",
+ "hiddenapi.go",
+ "hiddenapi_singleton.go",
+ "jacoco.go",
+ "java.go",
+ "jdeps.go",
+ "java_resources.go",
+ "kotlin.go",
+ "platform_compat_config.go",
+ "plugin.go",
+ "prebuilt_apis.go",
+ "proto.go",
+ "robolectric.go",
+ "sdk.go",
+ "sdk_library.go",
+ "support_libraries.go",
+ "sysprop.go",
+ "system_modules.go",
+ "testing.go",
+ "tradefed.go",
+ ],
+ testSrcs: [
+ "androidmk_test.go",
+ "app_test.go",
+ "device_host_converter_test.go",
+ "dexpreopt_test.go",
+ "dexpreopt_bootjars_test.go",
+ "java_test.go",
+ "jdeps_test.go",
+ "kotlin_test.go",
+ "plugin_test.go",
+ "sdk_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/java/androidmk.go b/java/androidmk.go
index 861bb5e99..75fb5fb02 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -69,7 +69,26 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
hideFromMake = true
}
- if !hideFromMake {
+ if hideFromMake {
+ // May still need to add some additional dependencies. This will be called
+ // once for the platform variant (even if it is not being used) and once each
+ // for the APEX specific variants. In order to avoid adding the dependency
+ // multiple times only add it for the platform variant.
+ checkedModulePaths := library.additionalCheckedModules
+ if library.IsForPlatform() && len(checkedModulePaths) != 0 {
+ mainEntries = android.AndroidMkEntries{
+ Class: "FAKE",
+ // Need at least one output file in order for this to take effect.
+ OutputFile: android.OptionalPathForPath(checkedModulePaths[0]),
+ Include: "$(BUILD_PHONY_PACKAGE)",
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(entries *android.AndroidMkEntries) {
+ entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", checkedModulePaths.Strings()...)
+ },
+ },
+ }
+ }
+ } else {
mainEntries = android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
DistFile: android.OptionalPathForPath(library.distFile),
diff --git a/java/app.go b/java/app.go
index e44b87d92..5bc09ff4d 100755
--- a/java/app.go
+++ b/java/app.go
@@ -421,12 +421,43 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if String(a.deviceProperties.Min_sdk_version) == "" {
ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.")
}
+ if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil {
+ a.checkJniLibsSdkVersion(ctx, minSdkVersion)
+ } else {
+ ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
+ }
}
a.checkPlatformAPI(ctx)
a.checkSdkVersions(ctx)
}
+// If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it.
+// This check is enforced for "updatable" APKs (including APK-in-APEX).
+// b/155209650: until min_sdk_version is properly supported, use sdk_version instead.
+// because, sdk_version is overridden by min_sdk_version (if set as smaller)
+// and linkType is checked with dependencies so we can be sure that the whole dependency tree
+// will meet the requirements.
+func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) {
+ // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType()
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) {
+ return
+ }
+ dep, _ := m.(*cc.Module)
+ // The domain of cc.sdk_version is "current" and <number>
+ // We can rely on sdkSpec to convert it to <number> so that "current" is handled
+ // properly regardless of sdk finalization.
+ jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx)
+ if err != nil || minSdkVersion < jniSdkVersion {
+ ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)",
+ dep.SdkVersion(), minSdkVersion, ctx.ModuleName())
+ return
+ }
+
+ })
+}
+
// Returns true if the native libraries should be stored in the APK uncompressed and the
// extractNativeLibs application flag should be set to false in the manifest.
func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool {
diff --git a/java/app_builder.go b/java/app_builder.go
index 967c55fcc..97ec269ee 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -26,16 +26,23 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
- Signapk = pctx.AndroidStaticRule("signapk",
+ Signapk, SignapkRE = remoteexec.StaticRules(pctx, "signapk",
blueprint.RuleParams{
- Command: `${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` +
+ Command: `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -Djava.library.path=$$(dirname ${config.SignapkJniLibrary}) ` +
`-jar ${config.SignapkCmd} $flags $certificates $in $out`,
CommandDeps: []string{"${config.SignapkCmd}", "${config.SignapkJniLibrary}"},
},
- "flags", "certificates")
+ &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "signapk"},
+ ExecStrategy: "${config.RESignApkExecStrategy}",
+ Inputs: []string{"${config.SignapkCmd}", "$in", "$$(dirname ${config.SignapkJniLibrary})", "$implicits"},
+ OutputFiles: []string{"$outCommaList"},
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"flags", "certificates"}, []string{"implicits", "outCommaList"})
)
var combineApk = pctx.AndroidStaticRule("combineApk",
@@ -90,16 +97,23 @@ func SignAppPackage(ctx android.ModuleContext, signedApk android.WritablePath, u
deps = append(deps, lineageFile)
}
+ rule := Signapk
+ args := map[string]string{
+ "certificates": strings.Join(certificateArgs, " "),
+ "flags": strings.Join(flags, " "),
+ }
+ if ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
+ rule = SignapkRE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ args["outCommaList"] = strings.Join(outputFiles.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: Signapk,
+ Rule: rule,
Description: "signapk",
Outputs: outputFiles,
Input: unsignedApk,
Implicits: deps,
- Args: map[string]string{
- "certificates": strings.Join(certificateArgs, " "),
- "flags": strings.Join(flags, " "),
- },
+ Args: args,
})
}
@@ -223,14 +237,20 @@ func TransformJniLibsToJar(ctx android.ModuleContext, outputFile android.Writabl
"-f", j.path.String())
}
+ rule := zip
+ args := map[string]string{
+ "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "),
+ }
+ if ctx.Config().IsEnvTrue("RBE_ZIP") {
+ rule = zipRE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: zip,
+ Rule: rule,
Description: "zip jni libs",
Output: outputFile,
Implicits: deps,
- Args: map[string]string{
- "jarArgs": strings.Join(proptools.NinjaAndShellEscapeList(jarArgs), " "),
- },
+ Args: args,
})
}
diff --git a/java/app_test.go b/java/app_test.go
index 8afd97d9e..e686f2780 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -473,6 +473,127 @@ func TestUpdatableApps(t *testing.T) {
}
}
+func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) {
+ testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ sdk_version: "current",
+ min_sdk_version: "current",
+ jni_libs: ["libjni"],
+ }
+
+ cc_library {
+ name: "libjni",
+ stl: "none",
+ system_shared_libs: [],
+ sdk_version: "current",
+ }
+ `)
+}
+
+func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) {
+ bp := cc.GatherRequiredDepsForTest(android.Android) + `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ sdk_version: "current",
+ min_sdk_version: "29",
+ jni_libs: ["libjni"],
+ }
+
+ cc_library {
+ name: "libjni",
+ stl: "none",
+ system_shared_libs: [],
+ sdk_version: "29",
+ }
+
+ ndk_prebuilt_object {
+ name: "ndk_crtbegin_so.29",
+ sdk_version: "29",
+ }
+
+ ndk_prebuilt_object {
+ name: "ndk_crtend_so.29",
+ sdk_version: "29",
+ }
+ `
+ fs := map[string][]byte{
+ "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil,
+ "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil,
+ "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil,
+ "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil,
+ }
+
+ ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs))
+
+ inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits
+ var crtbeginFound, crtendFound bool
+ for _, input := range inputs {
+ switch input.String() {
+ case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o":
+ crtbeginFound = true
+ case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o":
+ crtendFound = true
+ }
+ }
+ if !crtbeginFound || !crtendFound {
+ t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29")
+ }
+}
+
+func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) {
+ bp := cc.GatherRequiredDepsForTest(android.Android) + `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ sdk_version: "current",
+ min_sdk_version: "29", // this APK should support 29
+ jni_libs: ["libjni"],
+ }
+
+ cc_library {
+ name: "libjni",
+ stl: "none",
+ sdk_version: "current",
+ }
+ `
+ testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp)
+}
+
+func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) {
+ bp := cc.GatherRequiredDepsForTest(android.Android) + `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ updatable: true,
+ sdk_version: "current",
+ min_sdk_version: "29", // this APK should support 29
+ jni_libs: ["libjni"],
+ }
+
+ cc_library {
+ name: "libjni",
+ stl: "none",
+ shared_libs: ["libbar"],
+ system_shared_libs: [],
+ sdk_version: "27",
+ }
+
+ cc_library {
+ name: "libbar",
+ stl: "none",
+ system_shared_libs: [],
+ sdk_version: "current",
+ }
+ `
+ testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp)
+}
+
func TestResourceDirs(t *testing.T) {
testCases := []struct {
name string
diff --git a/java/builder.go b/java/builder.go
index 714d76aa5..a27e5c390 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -27,6 +27,7 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -38,17 +39,18 @@ var (
// this, all java rules write into separate directories and then are combined into a .jar file
// (if the rule produces .class files) or a .srcjar file (if the rule produces .java files).
// .srcjar files are unzipped into a temporary directory when compiled with javac.
- javac = pctx.AndroidRemoteStaticRule("javac", android.RemoteRuleSupports{Goma: true, RBE: true, RBEFlag: android.RBE_JAVAC},
+ // TODO(b/143658984): goma can't handle the --system argument to javac.
+ javac, javacRE = remoteexec.MultiCommandStaticRules(pctx, "javac",
blueprint.RuleParams{
Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`(if [ -s $srcJarDir/list ] || [ -s $out.rsp ] ; then ` +
- `${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ` +
+ `${config.SoongJavacWrapper} $javaTemplate${config.JavacCmd} ` +
`${config.JavacHeapFlags} ${config.JavacVmFlags} ${config.CommonJdkFlags} ` +
`$processorpath $processor $javacFlags $bootClasspath $classpath ` +
`-source $javaVersion -target $javaVersion ` +
`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list ; fi ) && ` +
- `${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
+ `$zipTemplate${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.JavacCmd}",
@@ -58,9 +60,21 @@ var (
CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
Rspfile: "$out.rsp",
RspfileContent: "$in",
- },
- "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
- "outDir", "annoDir", "javaVersion")
+ }, map[string]*remoteexec.REParams{
+ "$javaTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "lang": "java", "compiler": "javac"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$out"},
+ ExecStrategy: "${config.REJavacExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir",
+ "outDir", "annoDir", "javaVersion"}, nil)
_ = pctx.VariableFunc("kytheCorpus",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
@@ -111,10 +125,10 @@ var (
},
"abis", "allow-prereleased", "screen-densities", "sdk-version", "stem")
- turbine = pctx.AndroidStaticRule("turbine",
+ turbine, turbineRE = remoteexec.StaticRules(pctx, "turbine",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
+ `$reTemplate${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.TurbineJar} --output $out.tmp ` +
`--temp_dir "$outDir" --sources @$out.rsp --source_jars $srcJars ` +
`--javacopts ${config.CommonJdkFlags} ` +
`$javacFlags -source $javaVersion -target $javaVersion -- $bootClasspath $classpath && ` +
@@ -129,25 +143,45 @@ var (
RspfileContent: "$in",
Restat: true,
},
- "javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion")
-
- jar = pctx.AndroidStaticRule("jar",
+ &remoteexec.REParams{Labels: map[string]string{"type": "tool", "name": "turbine"},
+ ExecStrategy: "${config.RETurbineExecStrategy}",
+ Inputs: []string{"${config.TurbineJar}", "${out}.rsp", "$implicits"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"$out.tmp"},
+ OutputDirectories: []string{"$outDir"},
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion"}, []string{"implicits"})
+
+ jar, jarRE = remoteexec.StaticRules(pctx, "jar",
blueprint.RuleParams{
- Command: `${config.SoongZipCmd} -jar -o $out @$out.rsp`,
+ Command: `$reTemplate${config.SoongZipCmd} -jar -o $out @$out.rsp`,
CommandDeps: []string{"${config.SoongZipCmd}"},
Rspfile: "$out.rsp",
RspfileContent: "$jarArgs",
},
- "jarArgs")
-
- zip = pctx.AndroidStaticRule("zip",
+ &remoteexec.REParams{
+ ExecStrategy: "${config.REJarExecStrategy}",
+ Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"jarArgs"}, nil)
+
+ zip, zipRE = remoteexec.StaticRules(pctx, "zip",
blueprint.RuleParams{
Command: `${config.SoongZipCmd} -o $out @$out.rsp`,
CommandDeps: []string{"${config.SoongZipCmd}"},
Rspfile: "$out.rsp",
RspfileContent: "$jarArgs",
},
- "jarArgs")
+ &remoteexec.REParams{
+ ExecStrategy: "${config.REZipExecStrategy}",
+ Inputs: []string{"${config.SoongZipCmd}", "${out}.rsp", "$implicits"},
+ RSPFile: "${out}.rsp",
+ OutputFiles: []string{"$out"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ }, []string{"jarArgs"}, []string{"implicits"})
combineJar = pctx.AndroidStaticRule("combineJar",
blueprint.RuleParams{
@@ -199,6 +233,7 @@ var (
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
+ pctx.Import("android/soong/remoteexec")
}
type javaBuilderFlags struct {
@@ -340,20 +375,26 @@ func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.
deps = append(deps, classpath...)
deps = append(deps, flags.processorPath...)
+ rule := turbine
+ args := map[string]string{
+ "javacFlags": flags.javacFlags,
+ "bootClasspath": bootClasspath,
+ "srcJars": strings.Join(srcJars.Strings(), " "),
+ "classpath": classpath.FormTurbineClassPath("--classpath "),
+ "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(),
+ "javaVersion": flags.javaVersion.String(),
+ }
+ if ctx.Config().IsEnvTrue("RBE_TURBINE") {
+ rule = turbineRE
+ args["implicits"] = strings.Join(deps.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: turbine,
+ Rule: rule,
Description: "turbine",
Output: outputFile,
Inputs: srcFiles,
Implicits: deps,
- Args: map[string]string{
- "javacFlags": flags.javacFlags,
- "bootClasspath": bootClasspath,
- "srcJars": strings.Join(srcJars.Strings(), " "),
- "classpath": classpath.FormTurbineClassPath("--classpath "),
- "outDir": android.PathForModuleOut(ctx, "turbine", "classes").String(),
- "javaVersion": flags.javaVersion.String(),
- },
+ Args: args,
})
}
@@ -409,8 +450,12 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
outDir = filepath.Join(shardDir, outDir)
annoDir = filepath.Join(shardDir, annoDir)
}
+ rule := javac
+ if ctx.Config().IsEnvTrue("RBE_JAVAC") {
+ rule = javacRE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: javac,
+ Rule: rule,
Description: desc,
Output: outputFile,
Inputs: srcFiles,
@@ -433,8 +478,12 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab
func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath,
jarArgs []string, deps android.Paths) {
+ rule := jar
+ if ctx.Config().IsEnvTrue("RBE_JAR") {
+ rule = jarRE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: jar,
+ Rule: rule,
Description: "jar",
Output: outputFile,
Implicits: deps,
diff --git a/java/config/Android.bp b/java/config/Android.bp
new file mode 100644
index 000000000..198352187
--- /dev/null
+++ b/java/config/Android.bp
@@ -0,0 +1,15 @@
+bootstrap_go_package {
+ name: "soong-java-config",
+ pkgPath: "android/soong/java/config",
+ deps: [
+ "blueprint-proptools",
+ "soong-android",
+ "soong-remoteexec",
+ ],
+ srcs: [
+ "config.go",
+ "error_prone.go",
+ "kotlin.go",
+ "makevars.go",
+ ],
+}
diff --git a/java/config/config.go b/java/config/config.go
index 9ac5a50cb..337355d80 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -22,6 +22,7 @@ import (
_ "github.com/google/blueprint/bootstrap"
"android/soong/android"
+ "android/soong/remoteexec"
)
var (
@@ -139,30 +140,20 @@ func init() {
pctx.HostJavaToolVariable("MetalavaJar", "metalava.jar")
pctx.HostJavaToolVariable("DokkaJar", "dokka.jar")
pctx.HostJavaToolVariable("JetifierJar", "jetifier.jar")
+ pctx.HostJavaToolVariable("R8Jar", "r8-compat-proguard.jar")
+ pctx.HostJavaToolVariable("D8Jar", "d8.jar")
pctx.HostBinToolVariable("SoongJavacWrapper", "soong_javac_wrapper")
pctx.HostBinToolVariable("DexpreoptGen", "dexpreopt_gen")
- pctx.VariableFunc("JavacWrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("JAVAC_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
-
- pctx.VariableFunc("R8Wrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("R8_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
-
- pctx.VariableFunc("D8Wrapper", func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv("D8_WRAPPER"); override != "" {
- return override + " "
- }
- return ""
- })
+ pctx.VariableFunc("REJavaPool", remoteexec.EnvOverrideFunc("RBE_JAVA_POOL", "java16"))
+ pctx.VariableFunc("REJavacExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAVAC_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RED8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_D8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RER8ExecStrategy", remoteexec.EnvOverrideFunc("RBE_R8_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RETurbineExecStrategy", remoteexec.EnvOverrideFunc("RBE_TURBINE_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("RESignApkExecStrategy", remoteexec.EnvOverrideFunc("RBE_SIGNAPK_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REJarExecStrategy", remoteexec.EnvOverrideFunc("RBE_JAR_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
+ pctx.VariableFunc("REZipExecStrategy", remoteexec.EnvOverrideFunc("RBE_ZIP_EXEC_STRATEGY", remoteexec.LocalExecStrategy))
pctx.HostJavaToolVariable("JacocoCLIJar", "jacoco-cli.jar")
diff --git a/java/dex.go b/java/dex.go
index 62f17c6d8..9e61e95ad 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -21,41 +21,70 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/remoteexec"
)
-var d8 = pctx.AndroidRemoteStaticRule("d8", android.RemoteRuleSupports{RBE: true, RBEFlag: android.RBE_D8},
+var d8, d8RE = remoteexec.MultiCommandStaticRules(pctx, "d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `${config.D8Wrapper}${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
- `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
+ `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.D8Cmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
- },
- "outDir", "d8Flags", "zipFlags")
+ }, map[string]*remoteexec.REParams{
+ "$d8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "d8"},
+ Inputs: []string{"${config.D8Jar}"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$outDir/classes.dex.jar"},
+ ExecStrategy: "${config.RED8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "d8Flags", "zipFlags"}, nil)
-var r8 = pctx.AndroidRemoteStaticRule("r8", android.RemoteRuleSupports{RBE: true, RBEFlag: android.RBE_R8},
+var r8, r8RE = remoteexec.MultiCommandStaticRules(pctx, "r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && ` +
- `${config.R8Wrapper}${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
+ `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
`--force-proguard-compatibility ` +
`--no-data-resources ` +
`-printmapping $outDict ` +
`$r8Flags && ` +
`touch "$outDict" && ` +
- `${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
+ `$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
`${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.R8Cmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
- },
- "outDir", "outDict", "r8Flags", "zipFlags")
+ }, map[string]*remoteexec.REParams{
+ "$r8Template": &remoteexec.REParams{
+ Labels: map[string]string{"type": "compile", "compiler": "r8"},
+ Inputs: []string{"$implicits", "${config.R8Jar}"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ ToolchainInputs: []string{"${config.JavaCmd}"},
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ "$zipTemplate": &remoteexec.REParams{
+ Labels: map[string]string{"type": "tool", "name": "soong_zip"},
+ Inputs: []string{"${config.SoongZipCmd}", "$outDir"},
+ OutputFiles: []string{"$outDir/classes.dex.jar"},
+ ExecStrategy: "${config.RER8ExecStrategy}",
+ Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
+ },
+ }, []string{"outDir", "outDict", "r8Flags", "zipFlags"}, []string{"implicits"})
func (j *Module) dexCommonFlags(ctx android.ModuleContext) []string {
flags := j.deviceProperties.Dxflags
@@ -186,24 +215,34 @@ func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags,
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
j.proguardDictionary = proguardDictionary
r8Flags, r8Deps := j.r8Flags(ctx, flags)
+ rule := r8
+ args := map[string]string{
+ "r8Flags": strings.Join(r8Flags, " "),
+ "zipFlags": zipFlags,
+ "outDict": j.proguardDictionary.String(),
+ "outDir": outDir.String(),
+ }
+ if ctx.Config().IsEnvTrue("RBE_R8") {
+ rule = r8RE
+ args["implicits"] = strings.Join(r8Deps.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: r8,
+ Rule: rule,
Description: "r8",
Output: javalibJar,
ImplicitOutput: proguardDictionary,
Input: classesJar,
Implicits: r8Deps,
- Args: map[string]string{
- "r8Flags": strings.Join(r8Flags, " "),
- "zipFlags": zipFlags,
- "outDict": j.proguardDictionary.String(),
- "outDir": outDir.String(),
- },
+ Args: args,
})
} else {
d8Flags, d8Deps := j.d8Flags(ctx, flags)
+ rule := d8
+ if ctx.Config().IsEnvTrue("RBE_D8") {
+ rule = d8RE
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: d8,
+ Rule: rule,
Description: "d8",
Output: javalibJar,
Input: classesJar,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index b518e9c0d..2f0cbdb8c 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -611,10 +611,10 @@ func updatableBcpPackagesRule(ctx android.SingletonContext, image *bootImageConf
// Collect `permitted_packages` for updatable boot jars.
var updatablePackages []string
ctx.VisitAllModules(func(module android.Module) {
- if j, ok := module.(*Library); ok {
+ if j, ok := module.(PermittedPackagesForUpdatableBootJars); ok {
name := ctx.ModuleName(module)
if i := android.IndexList(name, updatableModules); i != -1 {
- pp := j.properties.Permitted_packages
+ pp := j.PermittedPackagesForUpdatableBootJars()
if len(pp) > 0 {
updatablePackages = append(updatablePackages, pp...)
} else {
diff --git a/java/java.go b/java/java.go
index c30dc4e50..2623d2c10 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1462,13 +1462,19 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
serviceFile := file.String()
zipargs = append(zipargs, "-C", filepath.Dir(serviceFile), "-f", serviceFile)
}
+ rule := zip
+ args := map[string]string{
+ "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
+ }
+ if ctx.Config().IsEnvTrue("RBE_ZIP") {
+ rule = zipRE
+ args["implicits"] = strings.Join(services.Strings(), ",")
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: zip,
+ Rule: rule,
Output: servicesJar,
Implicits: services,
- Args: map[string]string{
- "jarArgs": "-P META-INF/services/ " + strings.Join(proptools.NinjaAndShellEscapeList(zipargs), " "),
- },
+ Args: args,
})
jars = append(jars, servicesJar)
}
@@ -1839,6 +1845,17 @@ type Library struct {
InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
}
+// Provides access to the list of permitted packages from updatable boot jars.
+type PermittedPackagesForUpdatableBootJars interface {
+ PermittedPackagesForUpdatableBootJars() []string
+}
+
+var _ PermittedPackagesForUpdatableBootJars = (*Library)(nil)
+
+func (j *Library) PermittedPackagesForUpdatableBootJars() []string {
+ return j.properties.Permitted_packages
+}
+
func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
// Store uncompressed (and aligned) any dex files from jars in APEXes.
if am, ok := ctx.Module().(android.ApexModule); ok && !am.IsForPlatform() {
diff --git a/java/java_test.go b/java/java_test.go
index 385fe6afd..04717238d 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1465,6 +1465,33 @@ func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
`)
}
+func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ system: {
+ enabled: true,
+ },
+ default_to_stubs: true,
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["a.java"],
+ libs: ["foo"],
+ // does not have sdk_version set, should fallback to module,
+ // which will then fallback to system because the module scope
+ // is not enabled.
+ }
+ `)
+ // The baz library should depend on the system stubs jar.
+ bazLibrary := ctx.ModuleForTests("baz", "android_common").Rule("javac")
+ if expected, actual := `^-classpath .*:/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ t.Errorf("expected %q, found %#q", expected, actual)
+ }
+}
+
var compilerFlagsTestCases = []struct {
in string
out bool
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 17217ed41..03b63b9f8 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -438,6 +438,14 @@ type sdkLibraryProperties struct {
// disabled by default.
Module_lib ApiScopeProperties
+ // Determines if the stubs are preferred over the implementation library
+ // for linking, even when the client doesn't specify sdk_version. When this
+ // is set to true, such clients are provided with the widest API surface that
+ // this lib provides. Note however that this option doesn't affect the clients
+ // that are in the same APEX as this library. In that case, the clients are
+ // always linked with the implementation library. Default is false.
+ Default_to_stubs *bool
+
// Properties related to api linting.
Api_lint struct {
// Enable api linting.
@@ -1354,6 +1362,13 @@ func (module *SdkLibrary) withinSameApexAs(other android.Module) bool {
}
func (module *SdkLibrary) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
+ // If the client doesn't set sdk_version, but if this library prefers stubs over
+ // the impl library, let's provide the widest API surface possible. To do so,
+ // force override sdk_version to module_current so that the closest possible API
+ // surface could be found in selectHeaderJarsForSdkVersion
+ if module.defaultsToStubs() && !sdkVersion.specified() {
+ sdkVersion = sdkSpecFrom("module_current")
+ }
// Only provide access to the implementation library if it is actually built.
if module.requiresRuntimeImplementationLibrary() {
@@ -1517,6 +1532,10 @@ func (module *SdkLibrary) requiresRuntimeImplementationLibrary() bool {
return !proptools.Bool(module.sdkLibraryProperties.Api_only)
}
+func (module *SdkLibrary) defaultsToStubs() bool {
+ return proptools.Bool(module.sdkLibraryProperties.Default_to_stubs)
+}
+
// Defines how to name the individual component modules the sdk library creates.
type sdkLibraryComponentNamingScheme interface {
stubsLibraryModuleName(scope *apiScope, baseName string) string
@@ -2017,6 +2036,10 @@ type sdkLibrarySdkMemberProperties struct {
// The naming scheme.
Naming_scheme *string
+
+ // True if the java_sdk_library_import is for a shared library, false
+ // otherwise.
+ Shared_library *bool
}
type scopeProperties struct {
@@ -2051,12 +2074,16 @@ func (s *sdkLibrarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMembe
s.Libs = sdk.properties.Libs
s.Naming_scheme = sdk.commonSdkLibraryProperties.Naming_scheme
+ s.Shared_library = proptools.BoolPtr(sdk.sharedLibrary())
}
func (s *sdkLibrarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
if s.Naming_scheme != nil {
propertySet.AddProperty("naming_scheme", proptools.String(s.Naming_scheme))
}
+ if s.Shared_library != nil {
+ propertySet.AddProperty("shared_library", *s.Shared_library)
+ }
for _, apiScope := range allApiScopes {
if properties, ok := s.Scopes[apiScope]; ok {