diff --git a/java/Android.bp b/java/Android.bp index c0629414e..4bcae4ff7 100644 --- a/java/Android.bp +++ b/java/Android.bp @@ -81,6 +81,7 @@ bootstrap_go_package { "app_test.go", "bootclasspath_fragment_test.go", "device_host_converter_test.go", + "dex_test.go", "dexpreopt_test.go", "dexpreopt_bootjars_test.go", "droiddoc_test.go", diff --git a/java/base.go b/java/base.go index 9978a66fc..2f425cd83 100644 --- a/java/base.go +++ b/java/base.go @@ -872,6 +872,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB // classpath flags.bootClasspath = append(flags.bootClasspath, deps.bootClasspath...) flags.classpath = append(flags.classpath, deps.classpath...) + flags.dexClasspath = append(flags.dexClasspath, deps.dexClasspath...) flags.java9Classpath = append(flags.java9Classpath, deps.java9Classpath...) flags.processorPath = append(flags.processorPath, deps.processorPath...) flags.errorProneProcessorPath = append(flags.errorProneProcessorPath, deps.errorProneProcessorPath...) @@ -1090,6 +1091,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { flags.classpath = append(flags.classpath, deps.kotlinStdlib...) flags.classpath = append(flags.classpath, deps.kotlinAnnotations...) + flags.dexClasspath = append(flags.dexClasspath, deps.kotlinAnnotations...) + flags.kotlincClasspath = append(flags.kotlincClasspath, flags.bootClasspath...) flags.kotlincClasspath = append(flags.kotlincClasspath, flags.classpath...) @@ -1118,6 +1121,8 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { // Jar kotlin classes into the final jar after javac if BoolDefault(j.properties.Static_kotlin_stdlib, true) { kotlinJars = append(kotlinJars, deps.kotlinStdlib...) + } else { + flags.dexClasspath = append(flags.dexClasspath, deps.kotlinStdlib...) } } @@ -1842,6 +1847,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { } else if sdkDep.useFiles { // sdkDep.jar is actually equivalent to turbine header.jar. deps.classpath = append(deps.classpath, sdkDep.jars...) + deps.dexClasspath = append(deps.dexClasspath, sdkDep.jars...) deps.aidlPreprocess = sdkDep.aidl } else { deps.aidlPreprocess = sdkDep.aidl @@ -1866,7 +1872,9 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { if dep, ok := module.(SdkLibraryDependency); ok { switch tag { case libTag: - deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...) + depHeaderJars := dep.SdkHeaderJars(ctx, j.SdkVersion(ctx)) + deps.classpath = append(deps.classpath, depHeaderJars...) + deps.dexClasspath = append(deps.dexClasspath, depHeaderJars...) case staticLibTag: ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName) } @@ -1885,6 +1893,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...) case libTag, instrumentationForTag: deps.classpath = append(deps.classpath, dep.HeaderJars...) + deps.dexClasspath = append(deps.dexClasspath, dep.HeaderJars...) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...) addPlugins(&deps, dep.ExportedPlugins, dep.ExportedPluginClasses...) deps.disableTurbine = deps.disableTurbine || dep.ExportedPluginDisableTurbine @@ -1952,6 +1961,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { case libTag: checkProducesJars(ctx, dep) deps.classpath = append(deps.classpath, dep.Srcs()...) + deps.dexClasspath = append(deps.classpath, dep.Srcs()...) case staticLibTag: checkProducesJars(ctx, dep) deps.classpath = append(deps.classpath, dep.Srcs()...) diff --git a/java/builder.go b/java/builder.go index e64a61f5c..c48e3faa5 100644 --- a/java/builder.go +++ b/java/builder.go @@ -247,16 +247,33 @@ func init() { } type javaBuilderFlags struct { - javacFlags string - bootClasspath classpath - classpath classpath + javacFlags string + + // bootClasspath is the list of jars that form the boot classpath (generally the java.* and + // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses + // systemModules and java9Classpath instead. + bootClasspath classpath + + // classpath is the list of jars that form the classpath for javac and kotlinc rules. It + // contains header jars for all static and non-static dependencies. + classpath classpath + + // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains + // header jars for all non-static dependencies. Static dependencies have already been + // combined into the program jar. + dexClasspath classpath + + // java9Classpath is the list of jars that will be added to the classpath when targeting + // 1.9 or higher. It generally contains the android.* classes, while the java.* classes + // are provided by systemModules. java9Classpath classpath - processorPath classpath - processors []string - systemModules *systemModules - aidlFlags string - aidlDeps android.Paths - javaVersion javaVersion + + processorPath classpath + processors []string + systemModules *systemModules + aidlFlags string + aidlDeps android.Paths + javaVersion javaVersion errorProneExtraJavacFlags string errorProneProcessorPath classpath diff --git a/java/dex.go b/java/dex.go index 474694a51..448a7a19e 100644 --- a/java/dex.go +++ b/java/dex.go @@ -205,10 +205,10 @@ func (d *dexer) dexCommonFlags(ctx android.ModuleContext, func d8Flags(flags javaBuilderFlags) (d8Flags []string, d8Deps android.Paths) { d8Flags = append(d8Flags, flags.bootClasspath.FormRepeatedClassPath("--lib ")...) - d8Flags = append(d8Flags, flags.classpath.FormRepeatedClassPath("--lib ")...) + d8Flags = append(d8Flags, flags.dexClasspath.FormRepeatedClassPath("--lib ")...) d8Deps = append(d8Deps, flags.bootClasspath...) - d8Deps = append(d8Deps, flags.classpath...) + d8Deps = append(d8Deps, flags.dexClasspath...) return d8Flags, d8Deps } @@ -231,11 +231,11 @@ 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.classpath.FormJavaClassPath("-libraryjars")) + r8Flags = append(r8Flags, flags.dexClasspath.FormJavaClassPath("-libraryjars")) r8Deps = append(r8Deps, proguardRaiseDeps...) r8Deps = append(r8Deps, flags.bootClasspath...) - r8Deps = append(r8Deps, flags.classpath...) + r8Deps = append(r8Deps, flags.dexClasspath...) flagFiles := android.Paths{ android.PathForSource(ctx, "build/make/core/proguard.flags"), diff --git a/java/dex_test.go b/java/dex_test.go new file mode 100644 index 000000000..fbdccb65d --- /dev/null +++ b/java/dex_test.go @@ -0,0 +1,103 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package java + +import ( + "testing" + + "android/soong/android" +) + +func TestR8(t *testing.T) { + result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, ` + android_app { + name: "app", + srcs: ["foo.java"], + libs: ["lib"], + static_libs: ["static_lib"], + platform_apis: true, + } + + java_library { + name: "lib", + srcs: ["foo.java"], + } + + java_library { + name: "static_lib", + srcs: ["foo.java"], + } + `) + + app := result.ModuleForTests("app", "android_common") + lib := result.ModuleForTests("lib", "android_common") + staticLib := result.ModuleForTests("static_lib", "android_common") + + appJavac := app.Rule("javac") + appR8 := app.Rule("r8") + libHeader := lib.Output("turbine-combined/lib.jar").Output + staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output + + android.AssertStringDoesContain(t, "expected lib header jar in app javac classpath", + appJavac.Args["classpath"], libHeader.String()) + android.AssertStringDoesContain(t, "expected static_lib header jar in app javac classpath", + appJavac.Args["classpath"], staticLibHeader.String()) + + 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", + appR8.Args["r8Flags"], staticLibHeader.String()) +} + +func TestD8(t *testing.T) { + result := PrepareForTestWithJavaDefaultModulesWithoutFakeDex2oatd.RunTestWithBp(t, ` + java_library { + name: "foo", + srcs: ["foo.java"], + libs: ["lib"], + static_libs: ["static_lib"], + installable: true, + } + + java_library { + name: "lib", + srcs: ["foo.java"], + } + + java_library { + name: "static_lib", + srcs: ["foo.java"], + } + `) + + foo := result.ModuleForTests("foo", "android_common") + lib := result.ModuleForTests("lib", "android_common") + staticLib := result.ModuleForTests("static_lib", "android_common") + + fooJavac := foo.Rule("javac") + fooD8 := foo.Rule("d8") + libHeader := lib.Output("turbine-combined/lib.jar").Output + staticLibHeader := staticLib.Output("turbine-combined/static_lib.jar").Output + + android.AssertStringDoesContain(t, "expected lib header jar in foo javac classpath", + fooJavac.Args["classpath"], libHeader.String()) + android.AssertStringDoesContain(t, "expected static_lib header jar in foo javac classpath", + fooJavac.Args["classpath"], staticLibHeader.String()) + + android.AssertStringDoesContain(t, "expected lib header jar in foo d8 classpath", + fooD8.Args["d8Flags"], libHeader.String()) + android.AssertStringDoesNotContain(t, "expected no static_lib header jar in foo javac classpath", + fooD8.Args["d8Flags"], staticLibHeader.String()) +} diff --git a/java/java.go b/java/java.go index 895ce7af1..ddef34d2c 100644 --- a/java/java.go +++ b/java/java.go @@ -421,9 +421,25 @@ func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, } type deps struct { - classpath classpath - java9Classpath classpath - bootClasspath classpath + // bootClasspath is the list of jars that form the boot classpath (generally the java.* and + // android.* classes) for tools that still use it. javac targeting 1.9 or higher uses + // systemModules and java9Classpath instead. + bootClasspath classpath + + // classpath is the list of jars that form the classpath for javac and kotlinc rules. It + // contains header jars for all static and non-static dependencies. + classpath classpath + + // dexClasspath is the list of jars that form the classpath for d8 and r8 rules. It contains + // header jars for all non-static dependencies. Static dependencies have already been + // combined into the program jar. + dexClasspath classpath + + // java9Classpath is the list of jars that will be added to the classpath when targeting + // 1.9 or higher. It generally contains the android.* classes, while the java.* classes + // are provided by systemModules. + java9Classpath classpath + processorPath classpath errorProneProcessorPath classpath processorClasses []string @@ -1458,7 +1474,10 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { if ctx.OtherModuleHasProvider(module, JavaInfoProvider) { dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo) switch tag { - case libTag, staticLibTag: + case libTag: + flags.classpath = append(flags.classpath, dep.HeaderJars...) + flags.dexClasspath = append(flags.dexClasspath, dep.HeaderJars...) + case staticLibTag: flags.classpath = append(flags.classpath, dep.HeaderJars...) case bootClasspathTag: flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars...)