diff options
Diffstat (limited to 'java/java.go')
| -rw-r--r-- | java/java.go | 315 |
1 files changed, 213 insertions, 102 deletions
diff --git a/java/java.go b/java/java.go index 76e574eba..497b28510 100644 --- a/java/java.go +++ b/java/java.go @@ -143,6 +143,10 @@ type CompilerDeviceProperties struct { // If true, export a copy of the module as a -hostdex module for host testing. Hostdex *bool + // If false, prevent dexpreopting and stripping the dex file from the final jar. Defaults to + // true. + Dex_preopt *bool + // When targeting 1.9, override the modules to use with --system System_modules *string } @@ -156,8 +160,11 @@ type Module struct { protoProperties android.ProtoProperties deviceProperties CompilerDeviceProperties - // output file suitable for inserting into the classpath of another compile - classpathFile android.Path + // header jar file suitable for inserting into the bootclasspath/classpath of another compile + headerJarFile android.Path + + // full implementation jar file suitable for static dependency of another module compile + implementationJarFile android.Path // output file containing classes.dex dexJarFile android.Path @@ -178,7 +185,8 @@ type Module struct { } type Dependency interface { - ClasspathFiles() android.Paths + HeaderJars() android.Paths + ImplementationJars() android.Paths AidlIncludeDirs() android.Paths } @@ -263,13 +271,13 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { } } - toModule := func(m string) sdkDep { - return sdkDep{ - useModule: true, - module: m, - systemModules: m + "_system_modules", - } - } + //toModule := func(m string) sdkDep { + // return sdkDep{ + // useModule: true, + // module: m, + // systemModules: m + "_system_modules", + // } + //} if ctx.AConfig().UnbundledBuild() && v != "" { return toFile(v) @@ -280,12 +288,14 @@ func decodeSdkDep(ctx android.BaseContext, v string) sdkDep { return sdkDep{ useDefaultLibs: true, } - case "current": - return toModule("android_stubs_current") - case "system_current": - return toModule("android_system_stubs_current") - case "test_current": - return toModule("android_test_stubs_current") + // TODO(ccross): re-enable these once we generate stubs, until then + // use the stubs in prebuilts/sdk/*current + //case "current": + // return toModule("android_stubs_current") + //case "system_current": + // return toModule("android_system_stubs_current") + //case "test_current": + // return toModule("android_test_stubs_current") default: return toFile(v) } @@ -375,6 +385,7 @@ type deps struct { classpath android.Paths bootClasspath android.Paths staticJars android.Paths + staticHeaderJars android.Paths staticJarResources android.Paths aidlIncludeDirs android.Paths srcJars android.Paths @@ -390,6 +401,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { if sdkDep.invalidVersion { ctx.AddMissingDependencies([]string{sdkDep.module}) } else if sdkDep.useFiles { + // sdkDep.jar is actually equivalent to turbine header.jar. deps.classpath = append(deps.classpath, sdkDep.jar) deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, sdkDep.aidl) } @@ -420,12 +432,13 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { switch tag { case bootClasspathTag: - deps.bootClasspath = append(deps.bootClasspath, dep.ClasspathFiles()...) + deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars()...) case libTag: - deps.classpath = append(deps.classpath, dep.ClasspathFiles()...) + deps.classpath = append(deps.classpath, dep.HeaderJars()...) case staticLibTag: - deps.classpath = append(deps.classpath, dep.ClasspathFiles()...) - deps.staticJars = append(deps.staticJars, dep.ClasspathFiles()...) + deps.classpath = append(deps.classpath, dep.HeaderJars()...) + deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...) + deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...) case frameworkResTag: if ctx.ModuleName() == "framework" { // framework.jar has a one-off dependency on the R.java and Manifest.java files @@ -433,7 +446,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { // TODO(ccross): aapt java files should go in a src jar } case kotlinStdlibTag: - deps.kotlinStdlib = dep.ClasspathFiles() + deps.kotlinStdlib = dep.HeaderJars() default: panic(fmt.Errorf("unknown dependency %q for %q", otherName, ctx.ModuleName())) } @@ -444,20 +457,22 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { return deps } -func (j *Module) compile(ctx android.ModuleContext) { - - j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs) - - deps := j.collectDeps(ctx) +func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaBuilderFlags { var flags javaBuilderFlags + // javac flags. javacFlags := j.properties.Javacflags if ctx.AConfig().TargetOpenJDK9() { javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...) - j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...) + } + if len(javacFlags) > 0 { + // optimization. + ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " ")) + flags.javacFlags = "$javacFlags" } + // javaVersion flag. sdk := sdkStringToNumber(ctx, j.deviceProperties.Sdk_version) if j.properties.Java_version != nil { flags.javaVersion = *j.properties.Java_version @@ -465,43 +480,56 @@ func (j *Module) compile(ctx android.ModuleContext) { flags.javaVersion = "1.7" } else if ctx.Device() && sdk <= 26 || !ctx.AConfig().TargetOpenJDK9() { flags.javaVersion = "1.8" + } else if ctx.Device() && j.deviceProperties.Sdk_version != "" && sdk == 10000 { + // TODO(ccross): once we generate stubs we should be able to use 1.9 for sdk_version: "current" + flags.javaVersion = "1.8" } else { flags.javaVersion = "1.9" } + // classpath flags.bootClasspath.AddPaths(deps.bootClasspath) flags.classpath.AddPaths(deps.classpath) - + // systemModules if deps.systemModules != nil { flags.systemModules = append(flags.systemModules, deps.systemModules) } - if len(javacFlags) > 0 { - ctx.Variable(pctx, "javacFlags", strings.Join(javacFlags, " ")) - flags.javacFlags = "$javacFlags" - } - + // aidl flags. aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs) if len(aidlFlags) > 0 { + // optimization. ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " ")) flags.aidlFlags = "$aidlFlags" } - srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs) + return flags +} +func (j *Module) compile(ctx android.ModuleContext) { + + j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Export_aidl_include_dirs) + + deps := j.collectDeps(ctx) + flags := j.collectBuilderFlags(ctx, deps) + + if ctx.AConfig().TargetOpenJDK9() { + j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...) + } + srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs) if hasSrcExt(srcFiles.Strings(), ".proto") { flags = protoFlags(ctx, &j.protoProperties, flags) } var srcJars classpath srcFiles, srcJars = j.genSources(ctx, srcFiles, flags) - srcJars = append(srcJars, deps.srcJars...) - srcJars = append(srcJars, j.ExtraSrcJars...) var jars android.Paths + jarName := ctx.ModuleName() + ".jar" + if srcFiles.HasExt(".kt") { // If there are kotlin files, compile them first but pass all the kotlin and java files // kotlinc will use the java files to resolve types referenced by the kotlin files, but @@ -515,7 +543,7 @@ func (j *Module) compile(ctx android.ModuleContext) { flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...) flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...) - kotlinJar := android.PathForModuleOut(ctx, "classes-kt.jar") + kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName) TransformKotlinToClasses(ctx, kotlinJar, srcFiles, srcJars, flags) if ctx.Failed() { return @@ -528,7 +556,27 @@ func (j *Module) compile(ctx android.ModuleContext) { jars = append(jars, deps.kotlinStdlib...) } - if javaSrcFiles := srcFiles.FilterByExt(".java"); len(javaSrcFiles) > 0 { + javaSrcFiles := srcFiles.FilterByExt(".java") + var uniqueSrcFiles android.Paths + set := make(map[string]bool) + for _, v := range javaSrcFiles { + if _, found := set[v.String()]; !found { + set[v.String()] = true + uniqueSrcFiles = append(uniqueSrcFiles, v) + } + } + + if ctx.Device() && !ctx.AConfig().IsEnvFalse("TURBINE_ENABLED") { + // If sdk jar is java module, then directly return classesJar as header.jar + if j.Name() != "android_stubs_current" && j.Name() != "android_system_stubs_current" && + j.Name() != "android_test_stubs_current" { + j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName) + if ctx.Failed() { + return + } + } + } + if len(uniqueSrcFiles) > 0 { var extraJarDeps android.Paths if ctx.AConfig().IsEnvTrue("RUN_ERROR_PRONE") { // If error-prone is enabled, add an additional rule to compile the java files into @@ -536,13 +584,13 @@ func (j *Module) compile(ctx android.ModuleContext) { // a rebuild when error-prone is turned off). // TODO(ccross): Once we always compile with javac9 we may be able to conditionally // enable error-prone without affecting the output class files. - errorprone := android.PathForModuleOut(ctx, "classes-errorprone.list") + errorprone := android.PathForModuleOut(ctx, "errorprone", jarName) RunErrorProne(ctx, errorprone, javaSrcFiles, srcJars, flags) extraJarDeps = append(extraJarDeps, errorprone) } // Compile java sources into .class files - classes := android.PathForModuleOut(ctx, "classes-compiled.jar") + classes := android.PathForModuleOut(ctx, "javac", jarName) TransformJavaToClasses(ctx, classes, javaSrcFiles, srcJars, flags, extraJarDeps) if ctx.Failed() { return @@ -570,7 +618,7 @@ func (j *Module) compile(ctx android.ModuleContext) { } if len(resArgs) > 0 { - resourceJar := android.PathForModuleOut(ctx, "res.jar") + resourceJar := android.PathForModuleOut(ctx, "res", jarName) TransformResourcesToJar(ctx, resourceJar, resArgs, resDeps) if ctx.Failed() { return @@ -585,98 +633,151 @@ func (j *Module) compile(ctx android.ModuleContext) { manifest := android.OptionalPathForModuleSrc(ctx, j.properties.Manifest) // Combine the classes built from sources, any manifests, and any static libraries into - // classes.jar. If there is only one input jar this step will be skipped. + // classes.jar. If there is only one input jar this step will be skipped. var outputFile android.Path if len(jars) == 1 && !manifest.Valid() { // Optimization: skip the combine step if there is nothing to do outputFile = jars[0] } else { - combinedJar := android.PathForModuleOut(ctx, "classes.jar") - TransformJarsToJar(ctx, combinedJar, jars, manifest, false) + combinedJar := android.PathForModuleOut(ctx, "combined", jarName) + TransformJarsToJar(ctx, combinedJar, "for javac", jars, manifest, false, nil) outputFile = combinedJar } if j.properties.Jarjar_rules != nil { jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) // Transform classes.jar into classes-jarjar.jar - jarjarFile := android.PathForModuleOut(ctx, "classes-jarjar.jar") + jarjarFile := android.PathForModuleOut(ctx, "jarjar", jarName) TransformJarJar(ctx, jarjarFile, outputFile, jarjar_rules) outputFile = jarjarFile if ctx.Failed() { return } } - - j.classpathFile = outputFile + j.implementationJarFile = outputFile + if j.headerJarFile == nil { + j.headerJarFile = j.implementationJarFile + } if ctx.Device() && j.installable() { - dxFlags := j.deviceProperties.Dxflags - if false /* emma enabled */ { - // If you instrument class files that have local variable debug information in - // them emma does not correctly maintain the local variable table. - // This will cause an error when you try to convert the class files for Android. - // The workaround here is to build different dex file here based on emma switch - // then later copy into classes.dex. When emma is on, dx is run with --no-locals - // option to remove local variable information - dxFlags = append(dxFlags, "--no-locals") + outputFile = j.compileDex(ctx, flags, outputFile, jarName) + if ctx.Failed() { + return } + } + ctx.CheckbuildFile(outputFile) + j.outputFile = outputFile +} - if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" { - dxFlags = append(dxFlags, "--no-optimize") - } +func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles android.Paths, srcJars classpath, + deps deps, flags javaBuilderFlags, jarName string) android.Path { - if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" { - dxFlags = append(dxFlags, - "--debug", - "--verbose", - "--dump-to="+android.PathForModuleOut(ctx, "classes.lst").String(), - "--dump-width=1000") + var jars android.Paths + if len(srcFiles) > 0 { + // Compile java sources into turbine.jar. + turbineJar := android.PathForModuleOut(ctx, "turbine", jarName) + TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags) + if ctx.Failed() { + return nil } + jars = append(jars, turbineJar) + } - var minSdkVersion string - switch j.deviceProperties.Sdk_version { - case "", "current", "test_current", "system_current": - minSdkVersion = strconv.Itoa(ctx.AConfig().DefaultAppTargetSdkInt()) - default: - minSdkVersion = j.deviceProperties.Sdk_version + // Combine any static header libraries into classes-header.jar. If there is only + // one input jar this step will be skipped. + var headerJar android.Path + jars = append(jars, deps.staticHeaderJars...) + + if len(jars) == 0 { + panic("The turbine.jar is empty without any sources and static libs.") + } else { + // we cannot skip the combine step for now if there is only one jar + // since we have to strip META-INF/TRANSITIVE dir from turbine.jar + combinedJar := android.PathForModuleOut(ctx, "turbine-combined", jarName) + TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{}, false, []string{"META-INF"}) + headerJar = combinedJar + } + + if j.properties.Jarjar_rules != nil { + jarjar_rules := android.PathForModuleSrc(ctx, *j.properties.Jarjar_rules) + // Transform classes.jar into classes-jarjar.jar + jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName) + TransformJarJar(ctx, jarjarFile, headerJar, jarjar_rules) + headerJar = jarjarFile + if ctx.Failed() { + return nil } + } + + return headerJar +} - dxFlags = append(dxFlags, "--min-sdk-version="+minSdkVersion) +func (j *Module) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, + classesJar android.Path, jarName string) android.Path { + + dxFlags := j.deviceProperties.Dxflags + if false /* emma enabled */ { + // If you instrument class files that have local variable debug information in + // them emma does not correctly maintain the local variable table. + // This will cause an error when you try to convert the class files for Android. + // The workaround here is to build different dex file here based on emma switch + // then later copy into classes.dex. When emma is on, dx is run with --no-locals + // option to remove local variable information + dxFlags = append(dxFlags, "--no-locals") + } - flags.dxFlags = strings.Join(dxFlags, " ") + if ctx.AConfig().Getenv("NO_OPTIMIZE_DX") != "" { + dxFlags = append(dxFlags, "--no-optimize") + } - desugarFlags := []string{ - "--min_sdk_version " + minSdkVersion, - "--desugar_try_with_resources_if_needed=false", - "--allow_empty_bootclasspath", - } + if ctx.AConfig().Getenv("GENERATE_DEX_DEBUG") != "" { + dxFlags = append(dxFlags, + "--debug", + "--verbose", + "--dump-to="+android.PathForModuleOut(ctx, "classes.lst").String(), + "--dump-width=1000") + } - if inList("--core-library", dxFlags) { - desugarFlags = append(desugarFlags, "--core_library") - } + var minSdkVersion string + switch j.deviceProperties.Sdk_version { + case "", "current", "test_current", "system_current": + minSdkVersion = strconv.Itoa(ctx.AConfig().DefaultAppTargetSdkInt()) + default: + minSdkVersion = j.deviceProperties.Sdk_version + } - flags.desugarFlags = strings.Join(desugarFlags, " ") + dxFlags = append(dxFlags, "--min-sdk-version="+minSdkVersion) - desugarJar := android.PathForModuleOut(ctx, "classes-desugar.jar") - TransformDesugar(ctx, desugarJar, outputFile, flags) - outputFile = desugarJar - if ctx.Failed() { - return - } + flags.dxFlags = strings.Join(dxFlags, " ") - // Compile classes.jar into classes.dex and then javalib.jar - javalibJar := android.PathForModuleOut(ctx, "javalib.jar") - TransformClassesJarToDexJar(ctx, javalibJar, desugarJar, flags) - outputFile = javalibJar - if ctx.Failed() { - return - } + desugarFlags := []string{ + "--min_sdk_version " + minSdkVersion, + "--desugar_try_with_resources_if_needed=false", + "--allow_empty_bootclasspath", + } - j.dexJarFile = outputFile + if inList("--core-library", dxFlags) { + desugarFlags = append(desugarFlags, "--core_library") } - ctx.CheckbuildFile(outputFile) - j.outputFile = outputFile + + flags.desugarFlags = strings.Join(desugarFlags, " ") + + desugarJar := android.PathForModuleOut(ctx, "desugar", jarName) + TransformDesugar(ctx, desugarJar, classesJar, flags) + if ctx.Failed() { + return nil + } + + // Compile classes.jar into classes.dex and then javalib.jar + javalibJar := android.PathForModuleOut(ctx, "dex", jarName) + TransformClassesJarToDexJar(ctx, javalibJar, desugarJar, flags) + if ctx.Failed() { + return nil + } + + j.dexJarFile = javalibJar + return javalibJar } func (j *Module) installable() bool { @@ -685,8 +786,12 @@ func (j *Module) installable() bool { var _ Dependency = (*Library)(nil) -func (j *Module) ClasspathFiles() android.Paths { - return android.Paths{j.classpathFile} +func (j *Module) HeaderJars() android.Paths { + return android.Paths{j.headerJarFile} +} + +func (j *Module) ImplementationJars() android.Paths { + return android.Paths{j.implementationJarFile} } func (j *Module) AidlIncludeDirs() android.Paths { @@ -813,6 +918,8 @@ func BinaryHostFactory() android.Module { type ImportProperties struct { Jars []string + + Sdk_version string } type Import struct { @@ -844,13 +951,17 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.classpathFiles = android.PathsForModuleSrc(ctx, j.properties.Jars) outputFile := android.PathForModuleOut(ctx, "classes.jar") - TransformJarsToJar(ctx, outputFile, j.classpathFiles, android.OptionalPath{}, false) + TransformJarsToJar(ctx, outputFile, "for prebuilts", j.classpathFiles, android.OptionalPath{}, false, nil) j.combinedClasspathFile = outputFile } var _ Dependency = (*Import)(nil) -func (j *Import) ClasspathFiles() android.Paths { +func (j *Import) HeaderJars() android.Paths { + return j.classpathFiles +} + +func (j *Import) ImplementationJars() android.Paths { return j.classpathFiles } |